View Javadoc
1 /* 2 * JBoss, the OpenSource J2EE webOS 3 * 4 * Distributable under LGPL license. 5 * See terms of license at gnu.org. 6 */ 7 package net.sf.panoptes.model.component.registry; 8 9 import java.util.ArrayList; 10 import java.util.HashMap; 11 import java.util.Hashtable; 12 import java.util.Iterator; 13 import java.util.List; 14 import java.util.Map; 15 16 import net.sf.panoptes.model.component.Component; 17 import net.sf.panoptes.model.node.Node; 18 19 import org.apache.log4j.Logger; 20 21 /*** 22 * The registry for component name - component reference mapping. Original code 23 * from JBoss. 24 * 25 * @see net.sf.panoptes.model.component.IComponent 26 * @see net.sf.panoptes.model.component.registry.ComponentEntry 27 * 28 */ 29 public class ComponentRegistry { 30 // Attributes ---------------------------------------------------- 31 32 /*** 33 * A map of domain name to another map containing object name canonical 34 * key properties to registry entries. 35 * domain -> canonicalKeyProperties -> MBeanEntry 36 */ 37 private Map domainMap = new HashMap(); 38 39 /*** 40 * The default domain for this registry 41 */ 42 private String defaultDomain; 43 44 /*** 45 * Sequence number for the MBeanComponent server registration notifications. 46 */ 47 private long registrationNotificationSequence = 1; 48 49 /*** 50 * Sequence number for the MBeanComponent server unregistration notifications. 51 */ 52 private long unregistrationNotificationSequence = 1; 53 54 // Static -------------------------------------------------------- 55 56 /*** 57 * The logger 58 */ 59 private static Logger log = Logger.getLogger(ComponentRegistry.class); 60 61 // Constructors -------------------------------------------------- 62 63 /*** 64 * Constructs a new ComponentRegistry.<p> 65 * 66 */ 67 public ComponentRegistry() { 68 } 69 70 // MBeanRegistry Implementation ---------------------------------- 71 72 public void registerComponent(Component component, ComponentName name) 73 throws ComponentAlreadyExistsException { 74 boolean registrationDone = true; 75 ComponentName regName = name; 76 try { 77 regName = validateAndQualifyName(regName); 78 79 try { 80 81 ComponentEntry entry = new ComponentEntry(regName, component); 82 add(entry); 83 component.setComponentName(name); 84 component.setComponentRegistry(this); 85 component.init(); 86 87 try { 88 long sequence; 89 synchronized (this) { 90 sequence = registrationNotificationSequence++; 91 } 92 93 } catch (Throwable t) { 94 // Problem, remove the mbean from the registry 95 remove(regName); 96 97 throw t; 98 } 99 } 100 // Thrown by the registry 101 catch (ComponentAlreadyExistsException e) { 102 throw e; 103 } catch (Throwable t) { 104 // Something is broken 105 log.error("Unexpected Exception:", t); 106 107 throw t; 108 } 109 } catch (ComponentAlreadyExistsException e) { 110 // It was already registered 111 registrationDone = false; 112 throw e; 113 } catch (Throwable t) { 114 // Some other error 115 registrationDone = false; 116 } 117 } 118 119 public void unregisterMBean(ComponentName name) throws ComponentNotFoundException { 120 ComponentEntry entry = get(name); 121 Object resource = entry.getComponent(); 122 123 // It is no longer registered 124 remove(name); 125 } 126 127 public synchronized ComponentEntry get(ComponentName name) throws ComponentNotFoundException { 128 if (name == null) 129 throw new ComponentNotFoundException("null object name"); 130 131 // Determine the domain and retrieve its entries 132 String domain = name.getDomain(); 133 134 if (domain.length() == 0) 135 domain = defaultDomain; 136 137 String props = name.getCanonicalKeyPropertyListString(); 138 Map mbeanMap = (Map) domainMap.get(domain); 139 140 // Retrieve the mbean entry 141 Object o = null; 142 if (null == mbeanMap || null == (o = mbeanMap.get(props))) 143 throw new ComponentNotFoundException(name + " is not registered."); 144 145 // We are done 146 return (ComponentEntry) o; 147 } 148 149 public String getDefaultDomain() { 150 return defaultDomain; 151 } 152 153 public synchronized Node getObjectInstance(ComponentName name) throws ComponentNotFoundException { 154 if (!contains(name)) 155 throw new ComponentNotFoundException(name + " not registered."); 156 157 return get(name).getComponent(); 158 } 159 160 161 public synchronized boolean contains(ComponentName name) { 162 // null safety check 163 if (name == null) 164 return false; 165 166 // Determine the domain and retrieve its entries 167 String domain = name.getDomain(); 168 169 if (domain.length() == 0) 170 domain = defaultDomain; 171 172 String props = name.getCanonicalKeyPropertyListString(); 173 Map mbeanMap = (Map) domainMap.get(domain); 174 175 // Return the result 176 return (null != mbeanMap && mbeanMap.containsKey(props)); 177 } 178 179 public synchronized int getSize() { 180 int retval = 0; 181 182 for (Iterator iterator = domainMap.values().iterator(); iterator.hasNext();) { 183 retval += ((Map) iterator.next()).size(); 184 } 185 return retval; 186 } 187 188 public synchronized List findEntries(ComponentName pattern) { 189 ArrayList retval = new ArrayList(); 190 191 // There are a couple of shortcuts we can employ to make this a 192 // bit faster - they're commented. 193 194 // First, if pattern == null or pattern.getCanonicalName() == "*:*" we want the 195 // set of all MBeans. 196 if (pattern == null || pattern.getCanonicalName().equals("*:*")) { 197 for (Iterator domainIter = domainMap.values().iterator(); domainIter.hasNext();) { 198 for (Iterator mbeanIter = ((Map) domainIter.next()).values().iterator(); mbeanIter.hasNext();) { 199 retval.add(mbeanIter.next()); 200 } 201 } 202 } 203 // Next, if !pattern.isPattern() then we are doing a simple get (maybe defaultDomain). 204 else if (!pattern.isPattern()) { 205 // simple get 206 try { 207 retval.add(get(pattern)); 208 } catch (ComponentNotFoundException e) { 209 // we don't care 210 } 211 } 212 // Now we have to do a brute force, oh well. 213 else { 214 String patternDomain = pattern.getDomain(); 215 if (patternDomain.length() == 0) 216 patternDomain = defaultDomain; 217 boolean patternIsPropertyPattern = true; pattern.isPropertyPattern(); 218 String patternCanonicalKPS = pattern.getCanonicalKeyPropertyListString(); 219 Object[] propkeys = null; 220 Object[] propvals = null; 221 222 // prebuild arrays of keys and values for quick comparison 223 // when isPropertyPattern(). 224 if (patternIsPropertyPattern) { 225 Hashtable patternKPList = pattern.getKeyPropertyList(); 226 propkeys = new Object[patternKPList.size()]; 227 propvals = new Object[propkeys.length]; 228 229 int i = 0; 230 for (Iterator iterator = patternKPList.entrySet().iterator(); iterator.hasNext(); i++) { 231 Map.Entry mapEntry = (Map.Entry) iterator.next(); 232 propkeys[i] = mapEntry.getKey(); 233 propvals[i] = mapEntry.getValue(); 234 } 235 } 236 237 // Here we go, step through every domain and see if our pattern matches before optionally checking 238 // each ObjectName's properties for a match. 239 for (Iterator domainIter = domainMap.entrySet().iterator(); domainIter.hasNext();) { 240 Map.Entry mapEntry = (Map.Entry) domainIter.next(); 241 if (domainMatches((String) mapEntry.getKey(), patternDomain)) { 242 // yes it's a label, sue me. 243 CHOOSE_MBEAN : for ( 244 Iterator mbeanIter = ((Map) mapEntry.getValue()).values().iterator(); mbeanIter.hasNext();) { 245 ComponentEntry entry = (ComponentEntry) mbeanIter.next(); 246 ComponentName name = entry.getComponentName(); 247 248 if (patternIsPropertyPattern) { 249 // another shortcut - we only compare the key properties list of the registered MBeanComponent 250 // if properties have been specifed in the pattern (i.e. something other than just "*") 251 if (propkeys.length > 0) { 252 Hashtable nameKPList = name.getKeyPropertyList(); 253 254 for (int i = 0; i < propkeys.length; i++) { 255 // skip the current MBeanComponent if there isn't a match 256 if (!propvals[i].equals(nameKPList.get(propkeys[i]))) { 257 continue CHOOSE_MBEAN; 258 } 259 } 260 } 261 retval.add(entry); 262 } else { 263 // Ok, it's a like-for-like comparison of the keyProperties. 264 // Knowing how our implementation of ObjectName works, it's *much* 265 // faster to compare the canonicalKeyProperties strings than it 266 // is to compare the two hashtables. 267 if (patternCanonicalKPS.equals(name.getCanonicalKeyPropertyListString())) { 268 retval.add(entry); 269 } 270 } 271 } 272 } 273 } 274 } 275 276 return retval; 277 } 278 279 /*** 280 * Compare the src and pat strings where ? and * chars are significant. 281 * 282 * @author <a href="mailto:trevor@protocool.com">Trevor Squires</a>. 283 */ 284 protected boolean domainMatches(String src, String pat) { 285 if (src.equals("*")) // no point doing more that we have to... 286 { 287 return true; 288 } 289 return domainMatches(src.toCharArray(), 0, pat.toCharArray(), 0); 290 } 291 292 /*** 293 * Compare the src and pat char arrays where ? and * chars are significant. 294 * 295 * I arrived at this solution after quite a bit of trial and error - it's 296 * all a bit interwoven. Obviously I'm no good at parsers and there must 297 * be a clearer or more elegant way to do this. I'm suitably in awe of 298 * the perl regex hackers now. 299 * 300 * @author <a href="mailto:trevor@protocool.com">Trevor Squires</a>. 301 */ 302 protected boolean domainMatches(char[] src, int spos, char[] pat, int ppos) { 303 int slen = src.length; 304 int plen = pat.length; 305 306 while (ppos < plen) { 307 char c = pat[ppos++]; 308 if ('?' == c) { 309 // eat a src character and make sure we're not 310 // already at the end 311 if (spos++ == slen) { 312 return false; 313 } 314 } else if ('*' == c) { 315 if (ppos == plen) // shortcut - * at the end of the pattern 316 { 317 return true; 318 } 319 320 // hammer the src chars recursively until we 321 // get a match or we drop off the end of src 322 do { 323 if (domainMatches(src, spos, pat, ppos)) { 324 return true; 325 } 326 } while (++spos < slen); 327 } else if (spos == slen || c != src[spos++]) { 328 return false; 329 } 330 } 331 // fell through with no falses so make sure all of src was examined 332 return (spos == slen); 333 } 334 335 /*** 336 * Adds an MBeanComponent entry<p> 337 * 338 * WARNING: The object name should be fully qualified. 339 * 340 * @param entry the MBeanComponent entry to add 341 * @exception InstanceAlreadyExistsException when the MBeanComponent's object name 342 * is already registered 343 */ 344 protected synchronized void add(ComponentEntry entry) throws ComponentAlreadyExistsException { 345 // Determine the components's name and properties 346 ComponentName name = entry.getComponentName(); 347 String domain = name.getDomain(); 348 String props = name.getCanonicalKeyPropertyListString(); 349 350 // Create a properties -> entry map if we don't have one 351 Map mbeanMap = (Map) domainMap.get(domain); 352 if (mbeanMap == null) { 353 mbeanMap = new HashMap(); 354 domainMap.put(domain, mbeanMap); 355 } 356 357 // Make sure we aren't already registered 358 if (mbeanMap.get(props) != null) 359 throw new ComponentAlreadyExistsException(name + " already registered."); 360 361 // Ok, we are registered 362 mbeanMap.put(props, entry); 363 } 364 365 /*** 366 * Removes an MBeanComponent entry 367 * 368 * WARNING: The object name should be fully qualified. 369 * 370 * @param name the object name of the entry to remove 371 * @exception InstanceNotFoundException when the object name is not 372 * registered 373 */ 374 protected synchronized void remove(ComponentName name) throws ComponentNotFoundException { 375 // Determine the MBeanComponent's name and properties 376 String domain = name.getDomain(); 377 String props = name.getCanonicalKeyPropertyListString(); 378 Map mbeanMap = (Map) domainMap.get(domain); 379 380 // Remove the entry, raise an exception when it didn't exist 381 if (null == mbeanMap || null == mbeanMap.remove(props)) 382 throw new ComponentNotFoundException(name + " not registered."); 383 } 384 385 /*** 386 * Validates and qualifies an MBeanComponent<p> 387 * 388 * Validates the name is not a pattern.<p> 389 * 390 * Adds the default domain if no domain is specified.<p> 391 * 392 * Checks the name is not in the reserved domain JMImplementation when 393 * the magicToken is not {@link org.jboss.mx.server.ServerConstants#JMI_DOMAIN JMI_DOMAIN} 394 * 395 * @param name the name to validate 396 * @param magicToken used to get access to the reserved domain 397 * @return the original name or the name prepended with the default domain 398 * if no domain is specified. 399 * @exception RuntimeOperationException containing an 400 * IllegalArgumentException for a problem with the name 401 */ 402 protected ComponentName validateAndQualifyName(ComponentName name) { 403 // Check for qualification 404 ComponentName result = qualifyName(name); 405 return result; 406 } 407 408 protected ComponentName qualifyName(ComponentName name) { 409 try { 410 if (name.getDomain().length() == 0) 411 return new ComponentName(defaultDomain + ":" + name.getCanonicalKeyPropertyListString()); 412 else 413 return name; 414 } catch (MalformedComponentNameException e) { 415 throw new IllegalArgumentException(e.toString()); 416 } 417 } 418 419 }

This page was automatically generated by Maven