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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 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 }