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.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: 519834 $ $Date: 2007-03-19 00:32:05 -0400 (Mon, 19 Mar 2007) $
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), null);
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), mapToNames(instances));
159 }
160 if (shortName == null) {
161 throw new GBeanNotFoundException("More then one GBean was found with type '" + type.getName() + "'", Collections.singleton(nameQuery), mapToNames(instances));
162 }
163 throw new GBeanNotFoundException("More then one GBean was found with shortName '" + shortName + "' and type '" + type.getName() + "'", Collections.singleton(nameQuery), mapToNames(instances));
164 }
165
166 return (GBeanInstance) instances.iterator().next();
167 }
168
169 private Set<AbstractName> mapToNames(Set<GBeanInstance> instances) {
170 Set<AbstractName> names = new HashSet<AbstractName>(instances.size());
171 for (GBeanInstance instance: instances) {
172 names.add(instance.getAbstractName());
173 }
174 return names;
175 }
176
177
178 /**
179 * Search the objectNameRegistry for GBeans matching a name pattern.
180 *
181 * @param pattern the object name pattern to search for
182 * @return an unordered Set<GBeanInstance> of GBeans that matched the pattern
183 */
184 public Set listGBeans(ObjectName pattern) {
185 pattern = normalizeObjectName(pattern);
186
187 // fairly dumb implementation that iterates the list of all registered GBeans
188 Map clone;
189 synchronized (this) {
190 clone = new HashMap(objectNameRegistry);
191 }
192 Set result = new HashSet(clone.size());
193 for (Iterator i = clone.entrySet().iterator(); i.hasNext();) {
194 Map.Entry entry = (Map.Entry) i.next();
195 ObjectName name = (ObjectName) entry.getKey();
196 if (pattern == null || pattern.apply(name)) {
197 result.add(entry.getValue());
198 }
199 }
200 return result;
201 }
202
203 public Set listGBeans(AbstractNameQuery query) {
204 Map clone;
205 synchronized (this) {
206 clone = new HashMap(infoRegistry);
207 }
208 Set result = new HashSet(clone.size());
209 for (Iterator i = clone.entrySet().iterator(); i.hasNext();) {
210 Map.Entry entry = (Map.Entry) i.next();
211 AbstractName abstractName = (AbstractName) entry.getKey();
212 GBeanInstance gbeanData = (GBeanInstance) entry.getValue();
213 if (query == null || query.matches(abstractName, gbeanData.getGBeanInfo().getInterfaces())) {
214 result.add(gbeanData);
215 }
216 }
217 return result;
218 }
219
220 private ObjectName normalizeObjectName(ObjectName objectName) {
221 if (objectName != null && objectName.getDomain().length() == 0) {
222 try {
223 return new ObjectName(kernelName, objectName.getKeyPropertyList());
224 } catch (MalformedObjectNameException e) {
225 throw new AssertionError(e);
226 }
227 }
228 return objectName;
229 }
230 }