001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.kernel;
018    
019    import java.lang.ref.WeakReference;
020    import java.lang.ref.ReferenceQueue;
021    import java.util.Map;
022    import java.util.HashMap;
023    import java.util.Set;
024    import java.util.Collections;
025    
026    /**
027     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
028     */
029    public final class KernelRegistry {
030        /**
031         * Index of kernel references by kernel name
032         */
033        private static final Map kernels = new HashMap();
034    
035        /**
036         * ReferenceQueue that watches the weak references to our kernels
037         */
038        private static final ReferenceQueue queue = new ReferenceQueue();
039    
040        public static Set getKernelNames() {
041            synchronized(kernels) {
042                return Collections.unmodifiableSet(kernels.keySet());
043            }
044        }
045    
046        /**
047         * Get a particular kernel indexed by a name
048         *
049         * @param name the name of the kernel to be obtained
050         * @return the kernel that was registered with that name
051         */
052        public static Kernel getKernel(String name) {
053            if (name == null) {
054                return getSingleKernel();
055            }
056            synchronized (kernels) {
057                processQueue();
058                KernelReference ref = (KernelReference) kernels.get(name);
059                if (ref != null) {
060                    return (Kernel) ref.get();
061                }
062            }
063            return null;
064        }
065    
066        /**
067         * Obtain the single kernel that's registered.
068         * <p/>
069         * <p>This method assumes that there is only one kernel registered and will throw an
070         * <code>IllegalStateException</code> if more than one has been registered.
071         *
072         * @return the single kernel that's registered
073         * @throws IllegalStateException if more than one
074         */
075        public static Kernel getSingleKernel() {
076            synchronized (kernels) {
077                processQueue();
078    
079                int size = kernels.size();
080                if (size > 1) throw new IllegalStateException("More than one kernel has been registered.");
081                if (size < 1) return null;
082    
083                Kernel result = (Kernel) ((KernelReference) kernels.values().iterator().next()).get();
084                if (result == null) {
085                    kernels.clear();
086                }
087                return result;
088            }
089        }
090    
091        public static void registerKernel(Kernel kernel) {
092            synchronized (kernels) {
093                String kernelName = kernel.getKernelName();
094                if (kernels.containsKey(kernelName)) {
095                    throw new IllegalStateException("A kernel is already running this kernel name: " + kernelName);
096                }
097                kernels.put(kernelName, new KernelReference(kernelName, kernel));
098            }
099        }
100    
101        public static void unregisterKernel(Kernel kernel) {
102            synchronized (kernels) {
103                kernels.remove(kernel.getKernelName());
104            }
105        }
106    
107        private static void processQueue() {
108            KernelReference kernelRef;
109            while ((kernelRef = (KernelReference) queue.poll()) != null) {
110                synchronized (kernels) {
111                    kernels.remove(kernelRef.key);
112                }
113            }
114        }
115    
116        private static class KernelReference extends WeakReference {
117            private final Object key;
118    
119            public KernelReference(Object key, Object kernel) {
120                super(kernel, queue);
121                this.key = key;
122            }
123        }
124    }