001    /**
002     *
003     * Copyright 2004 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  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.basic;
018    
019    import java.util.Collections;
020    import java.util.HashMap;
021    import java.util.HashSet;
022    import java.util.IdentityHashMap;
023    import java.util.Iterator;
024    import java.util.Map;
025    import java.util.Set;
026    import javax.management.ObjectName;
027    import javax.management.MalformedObjectNameException;
028    
029    import org.apache.geronimo.gbean.AbstractName;
030    import org.apache.geronimo.gbean.AbstractNameQuery;
031    import org.apache.geronimo.gbean.runtime.GBeanInstance;
032    import org.apache.geronimo.gbean.runtime.InstanceRegistry;
033    import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
034    import org.apache.geronimo.kernel.GBeanNotFoundException;
035    import org.apache.geronimo.kernel.Kernel;
036    
037    /**
038     * @version $Rev: 430508 $ $Date: 2006-08-10 12:56:47 -0700 (Thu, 10 Aug 2006) $
039     */
040    public class BasicRegistry implements InstanceRegistry {
041        private final Map objectNameRegistry = new HashMap();
042        private final Map infoRegistry = new HashMap();
043        private final IdentityHashMap instanceRegistry = new IdentityHashMap();
044        private String kernelName = "";
045    
046        /**
047         * Start the objectNameRegistry and associate it with a kernel.
048         *
049         * @param kernel the kernel to associate with
050         */
051        public void start(Kernel kernel) {
052            kernelName = kernel.getKernelName();
053        }
054    
055        /**
056         * Shut down the objectNameRegistry and unregister any GBeans
057         */
058        public void stop() {
059            synchronized (this) {
060                objectNameRegistry.clear();
061            }
062            kernelName = "";
063        }
064    
065        /**
066         * See if there is a GBean registered with a specific name.
067         *
068         * @param name the name of the GBean to check for
069         * @return true if there is a GBean registered with that name
070         */
071        public synchronized boolean isRegistered(ObjectName name) {
072            return objectNameRegistry.containsKey(normalizeObjectName(name));
073        }
074    
075        public synchronized boolean isRegistered(AbstractName refInfo) {
076            return infoRegistry.containsKey(refInfo);
077        }
078    
079        /**
080         * Register a GBean instance.
081         *
082         * @param gbeanInstance the GBean to register
083         * @throws GBeanAlreadyExistsException if there is already a GBean registered with the instance's name
084         */
085        public synchronized void register(GBeanInstance gbeanInstance) throws GBeanAlreadyExistsException {
086            ObjectName name = normalizeObjectName(gbeanInstance.getObjectNameObject());
087            if (objectNameRegistry.containsKey(name)) {
088                throw new GBeanAlreadyExistsException("GBean already registered: " + name);
089            }
090            objectNameRegistry.put(name, gbeanInstance);
091            infoRegistry.put(gbeanInstance.getAbstractName(), gbeanInstance);
092            gbeanInstance.setInstanceRegistry(this);
093        }
094    
095        public synchronized void unregister(AbstractName abstractName) throws GBeanNotFoundException {
096            GBeanInstance gbeanInstance = (GBeanInstance) infoRegistry.remove(abstractName);
097            if (gbeanInstance == null) {
098                throw new GBeanNotFoundException(abstractName);
099            }
100            objectNameRegistry.remove(gbeanInstance.getObjectNameObject());
101        }
102    
103        public synchronized void instanceCreated(Object instance, GBeanInstance gbeanInstance) {
104            instanceRegistry.put(instance, gbeanInstance);
105        }
106    
107        public synchronized void instanceDestroyed(Object instance) {
108            instanceRegistry.remove(instance);
109        }
110    
111        public synchronized GBeanInstance getGBeanInstanceByInstance(Object instance) {
112            return (GBeanInstance) instanceRegistry.get(instance);
113        }
114    
115        /**
116         * Return the GBeanInstance registered with the supplied name.
117         *
118         * @param name the name of the instance to return
119         * @return the GBeanInstance
120         * @throws GBeanNotFoundException if there is no GBean registered with the supplied name
121         */
122        public synchronized GBeanInstance getGBeanInstance(ObjectName name) throws GBeanNotFoundException {
123            GBeanInstance instance = (GBeanInstance) objectNameRegistry.get(normalizeObjectName(name));
124            if (instance == null) {
125                throw new GBeanNotFoundException(name);
126            }
127            return instance;
128        }
129    
130        public synchronized GBeanInstance getGBeanInstance(AbstractName abstractName) throws GBeanNotFoundException {
131            GBeanInstance instance = (GBeanInstance) infoRegistry.get(abstractName);
132            if (instance == null) {
133                throw new GBeanNotFoundException(abstractName);
134            }
135            return instance;
136        }
137    
138    
139        public synchronized GBeanInstance getGBeanInstance(String shortName, Class type) throws GBeanNotFoundException {
140            if (shortName == null && type == null) throw new IllegalArgumentException("shortName and type are both null");
141    
142            AbstractNameQuery nameQuery;
143            if (type == null) {
144                nameQuery = new AbstractNameQuery(null, Collections.singletonMap("name", shortName));
145            } else if (shortName == null) {
146                nameQuery = new AbstractNameQuery(null, Collections.EMPTY_MAP, type.getName());
147            } else {
148                nameQuery = new AbstractNameQuery(null, Collections.singletonMap("name", shortName), type.getName());
149            }
150            Set instances = listGBeans(nameQuery);
151    
152            if (instances.size() == 0) {
153                throw new GBeanNotFoundException("No GBeans found", Collections.singleton(nameQuery));
154            }
155    
156            if (instances.size() > 1) {
157                if (type == null) {
158                    throw new GBeanNotFoundException("More then one GBean was found with shortName '" + shortName + "'", Collections.singleton(nameQuery));
159                }
160                if (shortName == null) {
161                    throw new GBeanNotFoundException("More then one GBean was found with type '" + type.getName() + "'", Collections.singleton(nameQuery));
162                }
163                throw new GBeanNotFoundException("More then one GBean was found with shortName '" + shortName + "' and type '" + type.getName() + "'", Collections.singleton(nameQuery));
164            }
165    
166            GBeanInstance instance = (GBeanInstance) instances.iterator().next();
167            return instance;
168        }
169    
170    
171        /**
172         * Search the objectNameRegistry for GBeans matching a name pattern.
173         *
174         * @param pattern the object name pattern to search for
175         * @return an unordered Set<GBeanInstance> of GBeans that matched the pattern
176         */
177        public Set listGBeans(ObjectName pattern) {
178            pattern = normalizeObjectName(pattern);
179    
180            // fairly dumb implementation that iterates the list of all registered GBeans
181            Map clone;
182            synchronized (this) {
183                clone = new HashMap(objectNameRegistry);
184            }
185            Set result = new HashSet(clone.size());
186            for (Iterator i = clone.entrySet().iterator(); i.hasNext();) {
187                Map.Entry entry = (Map.Entry) i.next();
188                ObjectName name = (ObjectName) entry.getKey();
189                if (pattern == null || pattern.apply(name)) {
190                    result.add(entry.getValue());
191                }
192            }
193            return result;
194        }
195    
196        public Set listGBeans(AbstractNameQuery query) {
197            Map clone;
198            synchronized (this) {
199                clone = new HashMap(infoRegistry);
200            }
201            Set result = new HashSet(clone.size());
202            for (Iterator i = clone.entrySet().iterator(); i.hasNext();) {
203                Map.Entry entry = (Map.Entry) i.next();
204                AbstractName abstractName = (AbstractName) entry.getKey();
205                GBeanInstance gbeanData = (GBeanInstance) entry.getValue();
206                if (query == null || query.matches(abstractName, gbeanData.getGBeanInfo().getInterfaces())) {
207                    result.add(gbeanData);
208                }
209            }
210            return result;
211        }
212    
213        private ObjectName normalizeObjectName(ObjectName objectName) {
214            if (objectName != null && objectName.getDomain().length() == 0) {
215                try {
216                    return new ObjectName(kernelName, objectName.getKeyPropertyList());
217                } catch (MalformedObjectNameException e) {
218                    throw new AssertionError(e);
219                }
220            }
221            return objectName;
222        }
223    }