1 22 package org.jboss.mx.server.registry; 23 24 import java.util.ArrayList ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.Vector ; 29 import javax.management.Descriptor ; 30 import javax.management.DynamicMBean ; 31 import javax.management.InstanceAlreadyExistsException ; 32 import javax.management.InstanceNotFoundException ; 33 import javax.management.MBeanException ; 34 import javax.management.MBeanInfo ; 35 import javax.management.MBeanRegistration ; 36 import javax.management.MBeanRegistrationException ; 37 import javax.management.MBeanServer ; 38 import javax.management.MBeanServerDelegate ; 39 import javax.management.MBeanServerNotification ; 40 import javax.management.MalformedObjectNameException ; 41 import javax.management.NotCompliantMBeanException ; 42 import javax.management.ObjectInstance ; 43 import javax.management.ObjectName ; 44 import javax.management.ReflectionException ; 45 import javax.management.RuntimeErrorException ; 46 import javax.management.RuntimeMBeanException ; 47 import javax.management.RuntimeOperationsException ; 48 import javax.management.loading.ClassLoaderRepository ; 49 import javax.management.modelmbean.ModelMBeanInfo ; 50 import javax.management.modelmbean.RequiredModelMBean ; 51 52 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 53 import EDU.oswego.cs.dl.util.concurrent.SynchronizedLong; 54 import org.jboss.logging.Logger; 55 import org.jboss.mx.loading.LoaderRepository; 56 import org.jboss.mx.loading.RepositoryClassLoader; 57 import org.jboss.mx.metadata.MBeanCapability; 58 import org.jboss.mx.modelmbean.ModelMBeanConstants; 59 import org.jboss.mx.modelmbean.RequiredModelMBeanInvoker; 60 import org.jboss.mx.modelmbean.XMBean; 61 import org.jboss.mx.modelmbean.XMBeanConstants; 62 import org.jboss.mx.server.AbstractMBeanInvoker; 63 import org.jboss.mx.server.MBeanInvoker; 64 import org.jboss.mx.server.RawDynamicInvoker; 65 import org.jboss.mx.server.ServerConfig; 66 import org.jboss.mx.server.ServerObjectInstance; 67 import org.jboss.mx.util.ObjectNamePatternHelper; 68 import org.jboss.mx.util.ObjectNamePatternHelper.PropertyPattern; 69 import org.jboss.util.NestedRuntimeException; 70 71 90 public class BasicMBeanRegistry 91 implements MBeanRegistry 92 { 93 95 96 private static ServerConfig serverConfig = ServerConfig.getInstance(); 97 98 99 private static String JMI_DOMAIN = serverConfig.getJMIDomain(); 100 101 103 108 private Map domainMap = new ConcurrentReaderHashMap(); 109 110 113 private String defaultDomain; 114 115 118 private MBeanServer server; 119 120 123 private LoaderRepository loaderRepository; 124 125 128 protected final SynchronizedLong registrationNotificationSequence = new SynchronizedLong (1); 129 130 133 protected final SynchronizedLong unregistrationNotificationSequence = new SynchronizedLong (1); 134 135 138 protected MBeanServerDelegate delegate; 139 140 protected Vector fMbInfosToStore; 141 private ObjectName mbeanInfoService; 142 143 144 146 149 protected static Logger log = Logger.getLogger(BasicMBeanRegistry.class); 150 151 152 154 157 public BasicMBeanRegistry(MBeanServer server, String defaultDomain, ClassLoaderRepository clr) 158 { 159 this.server = server; 161 this.defaultDomain = defaultDomain; 162 163 try 164 { 165 loaderRepository = (LoaderRepository ) clr; 166 mbeanInfoService = new ObjectName ("user:service=MBeanInfoDB"); 167 } 168 catch (Exception e) 169 { 170 throw new NestedRuntimeException("Error instantiating registry", e); 171 } 172 } 173 174 175 177 public ObjectInstance registerMBean(Object object, ObjectName name, Map valueMap) 178 throws InstanceAlreadyExistsException , MBeanRegistrationException , NotCompliantMBeanException 179 { 180 ObjectName regName = name; 181 boolean registrationDone = true; 182 boolean invokedPreRegister = false; 183 String magicToken = null; 184 MBeanInvoker invoker = null; 185 186 if (object == null) 187 throw new RuntimeOperationsException ( 188 new IllegalArgumentException ("Attempting to register null object")); 189 190 MBeanCapability mbcap = MBeanCapability.of(object.getClass()); 192 193 try 194 { 195 196 if (valueMap != null) 197 magicToken = (String ) valueMap.get(JMI_DOMAIN); 198 199 int mbeanType = mbcap.getMBeanType(); 201 if (mbeanType == MBeanCapability.STANDARD_MBEAN) 202 { 203 invoker = new XMBean(object, XMBeanConstants.STANDARD_MBEAN); 204 } 205 else if (object instanceof MBeanInvoker) 206 { 207 invoker = (MBeanInvoker)object; 208 } 209 else if (mbeanType == MBeanCapability.DYNAMIC_MBEAN) 210 { 211 if( object instanceof RequiredModelMBean ) 212 invoker = new RequiredModelMBeanInvoker((DynamicMBean )object); 213 else 214 invoker = new RawDynamicInvoker((DynamicMBean )object); 215 } 216 217 MBeanEntry entry = new MBeanEntry(regName, invoker, object, valueMap); 219 AbstractMBeanInvoker.setMBeanEntry(entry); 220 regName = invokePreRegister(invoker, regName, magicToken); 221 invokedPreRegister = true; 222 223 try 224 { 225 MBeanInfo info = invoker.getMBeanInfo(); 226 verifyMBeanInfo(info, name); 227 entry.setResourceClassName(info.getClassName()); 228 229 231 entry.setObjectName(regName); 233 234 add(entry); 235 236 try 237 { 238 if (object instanceof ClassLoader ) 240 registerClassLoader((ClassLoader )object); 241 242 try 243 { 244 if (delegate != null) 245 sendRegistrationNotification (regName); 246 else if (serverConfig.getMBeanServerDelegateName().equals(name)) 247 delegate = (MBeanServerDelegate ) object; 248 249 ServerObjectInstance serverObjInst = new ServerObjectInstance 250 (regName, entry.getResourceClassName(), delegate.getMBeanServerId()); 251 252 persistIfRequired(invoker.getMBeanInfo(), regName); 253 254 return serverObjInst; 255 256 } 257 catch (Throwable t) 258 { 259 if (object instanceof ClassLoader ) 261 loaderRepository.removeClassLoader((ClassLoader )object); 262 263 throw t; 264 } 265 } 266 catch (Throwable t) 267 { 268 remove(regName); 270 throw t; 271 } 272 } 273 catch (NotCompliantMBeanException e) 275 { 276 throw e; 277 } 278 catch (InstanceAlreadyExistsException e) 280 { 281 throw e; 282 } 283 catch (Throwable t) 284 { 285 log.error("Unexpected Exception:", t); 287 throw t; 288 } 289 } 290 catch (NotCompliantMBeanException e) 291 { 292 registrationDone = false; 293 throw e; 294 } 295 catch (InstanceAlreadyExistsException e) 296 { 297 registrationDone = false; 299 throw e; 300 } 301 catch (MBeanRegistrationException e) 302 { 303 registrationDone = false; 305 log.warn(e.toString()); 306 throw e; 307 } 308 catch (RuntimeOperationsException e) 309 { 310 registrationDone = false; 312 throw e; 313 } 314 catch (Exception ex) 315 { 316 registrationDone = false; 318 NotCompliantMBeanException ncex = new NotCompliantMBeanException ("Cannot register MBean: " + name); 319 ncex.initCause(ex); 320 throw ncex; 321 } 322 catch (Throwable t) 323 { 324 log.error("Cannot register MBean", t); 326 registrationDone = false; 327 return null; 328 } 329 finally 330 { 331 if (invoker != null) 333 { 334 try 335 { 336 invoker.postRegister(new Boolean (registrationDone)); 337 } 338 catch(Exception e) 339 { 340 if( invokedPreRegister == true ) 342 { 343 if( e instanceof RuntimeException ) 344 throw new RuntimeMBeanException ((RuntimeException ) e); 345 else 346 throw new MBeanRegistrationException (e); 347 } 348 } 349 } 350 AbstractMBeanInvoker.setMBeanEntry(null); 351 } 352 } 353 354 360 private void verifyMBeanInfo(MBeanInfo info, ObjectName name) 361 throws NotCompliantMBeanException 362 { 363 try 364 { 365 if (info == null) 366 throw new NotCompliantMBeanException ("MBeanInfo cannot be null, for: " + name); 367 368 if (info.getClassName() == null) 369 throw new NotCompliantMBeanException ("Classname returned from MBeanInfo cannot be null, for: " + name); 370 } 371 catch (NotCompliantMBeanException ncex) 372 { 373 throw ncex; 374 } 375 catch (Throwable t) 376 { 377 NotCompliantMBeanException ncex = new NotCompliantMBeanException ("Cannot verify MBeanInfo, for: " + name); 378 ncex.initCause(t); 379 throw ncex; 380 } 381 } 382 383 389 protected void sendRegistrationNotification (ObjectName regName) 390 { 391 long sequence = registrationNotificationSequence.increment (); 392 delegate.sendNotification ( 393 new MBeanServerNotification ( 394 MBeanServerNotification.REGISTRATION_NOTIFICATION, 395 delegate, sequence, regName)); 396 } 397 398 407 protected ObjectName handlePreRegistration (MBeanRegistration registrationInterface, ObjectName regName) 408 throws Exception 409 { 410 ObjectName mbean = registrationInterface.preRegister (server, regName); 411 if (regName == null) 412 { 413 return mbean; 414 } 415 else 416 { 417 return regName; 418 } 419 } 420 421 422 429 protected void handlePreDeregister (MBeanRegistration registrationInterface) 430 throws Exception 431 { 432 registrationInterface.preDeregister (); 433 } 434 435 441 protected void registerClassLoader(ClassLoader cl) 442 { 443 if( (cl instanceof RepositoryClassLoader) == false ) 444 { 445 loaderRepository.addClassLoader(cl); 447 } 448 } 449 450 451 public void unregisterMBean(ObjectName name) 452 throws InstanceNotFoundException , MBeanRegistrationException 453 { 454 name = qualifyName(name); 455 if (name.getDomain().equals(JMI_DOMAIN)) 456 throw new RuntimeOperationsException (new IllegalArgumentException ( 457 "Not allowed to unregister: " + name.toString())); 458 459 MBeanEntry entry = get(name); 460 Object resource = entry.getResourceInstance(); 461 462 try 463 { 464 handlePreDeregister (entry.getInvoker()); 466 467 } 468 catch (Exception e) 469 { 470 if (e instanceof MBeanRegistrationException ) 472 throw (MBeanRegistrationException )e; 473 474 throw new MBeanRegistrationException (e, "preDeregister"); 475 } 476 477 if (resource instanceof ClassLoader ) 479 loaderRepository.removeClassLoader((ClassLoader )resource); 480 481 remove(name); 483 484 sendUnRegistrationNotification (name); 485 486 entry.getInvoker().postDeregister(); 487 } 488 489 495 protected void sendUnRegistrationNotification (ObjectName name) 496 { 497 long sequence = unregistrationNotificationSequence.increment (); 498 499 delegate.sendNotification ( 500 new MBeanServerNotification ( 501 MBeanServerNotification.UNREGISTRATION_NOTIFICATION, 502 delegate, 503 sequence, 504 name 505 ) 506 ); 507 } 508 509 public MBeanEntry get(ObjectName name) 510 throws InstanceNotFoundException 511 { 512 if (name == null) 513 throw new RuntimeOperationsException (new IllegalArgumentException ("null object name")); 514 515 String domain = name.getDomain(); 517 518 if (domain.length() == 0) 519 domain = defaultDomain; 520 521 String props = name.getCanonicalKeyPropertyListString(); 522 Map mbeanMap = getMBeanMap(domain, false); 523 524 Object o = null; 526 if (null == mbeanMap || null == (o = mbeanMap.get(props))) 527 throw new InstanceNotFoundException (name + " is not registered."); 528 529 return (MBeanEntry) o; 531 } 532 533 public String getDefaultDomain() 534 { 535 return defaultDomain; 536 } 537 538 public String [] getDomains() 539 { 540 ArrayList domains = new ArrayList (domainMap.size()); 541 for (Iterator iterator = domainMap.entrySet().iterator(); iterator.hasNext();) 542 { 543 Map.Entry entry = (Map.Entry ) iterator.next(); 544 String domainName = (String ) entry.getKey(); 545 Map mbeans = (Map ) entry.getValue(); 546 if (mbeans != null && mbeans.isEmpty() == false) 547 domains.add(domainName); 548 } 549 return (String []) domains.toArray(new String [domains.size()]); 550 } 551 552 public ObjectInstance getObjectInstance(ObjectName name) 553 throws InstanceNotFoundException 554 { 555 if (!contains(name)) 556 throw new InstanceNotFoundException (name + " not registered."); 557 558 return new ServerObjectInstance(qualifyName(name), 559 get(name).getResourceClassName(), delegate.getMBeanServerId()); 560 } 561 562 public Object getValue(ObjectName name, String key) 563 throws InstanceNotFoundException 564 { 565 return get(name).getValue(key); 566 } 567 568 public boolean contains(ObjectName name) 569 { 570 if (name == null) 572 return false; 573 574 String domain = name.getDomain(); 576 577 if (domain.length() == 0) 578 domain = defaultDomain; 579 580 String props = name.getCanonicalKeyPropertyListString(); 581 Map mbeanMap = getMBeanMap(domain, false); 582 583 return (null != mbeanMap && mbeanMap.containsKey(props)); 585 } 586 587 public int getSize() 588 { 589 int retval = 0; 590 for (Iterator iterator = domainMap.values().iterator(); iterator.hasNext();) 591 { 592 retval += ((Map )iterator.next()).size(); 593 } 594 return retval; 595 } 596 597 public List findEntries(ObjectName pattern) 598 { 599 ArrayList retval = new ArrayList (); 600 601 604 if (pattern == null || pattern.getCanonicalName().equals("*:*")) 607 { 608 for (Iterator domainIter = domainMap.values().iterator(); domainIter.hasNext();) 609 retval.addAll(((Map )domainIter.next()).values()); 610 } 611 else if (!pattern.isPattern()) 613 { 614 try 616 { 617 retval.add(get(pattern)); 618 } 619 catch (InstanceNotFoundException e) 620 { 621 } 623 } 624 else 626 { 627 String patternDomain = pattern.getDomain(); 628 if (patternDomain.length() == 0) 629 patternDomain = defaultDomain; 630 PropertyPattern propertyPattern = new PropertyPattern(pattern); 631 632 for (Iterator domainIter = domainMap.entrySet().iterator(); domainIter.hasNext();) 635 { 636 Map.Entry mapEntry = (Map.Entry ) domainIter.next(); 637 Map value = (Map ) mapEntry.getValue(); 638 if (value != null && value.isEmpty() == false) 639 { 640 if (ObjectNamePatternHelper.patternMatch((String ) mapEntry.getKey(), patternDomain)) 641 { 642 for (Iterator mbeanIter = value.values().iterator(); mbeanIter.hasNext();) 643 { 644 MBeanEntry entry = (MBeanEntry) mbeanIter.next(); 645 if (propertyPattern.patternMatch(entry.getObjectName())) 646 retval.add(entry); 647 } 648 } 649 } 650 } 651 } 652 653 return retval; 654 } 655 656 657 660 public void releaseRegistry() 661 { 664 server = null; 665 delegate = null; 666 667 for (Iterator iterator = domainMap.keySet().iterator(); iterator.hasNext();) 669 { 670 Map nextMap = (Map ) domainMap.get(iterator.next()); 671 672 if ( nextMap.size() > 0 ) 673 { 674 nextMap.clear(); 675 } 676 } 677 678 domainMap.clear(); 679 domainMap = null; 680 } 681 682 683 685 protected ObjectName invokePreRegister(MBeanInvoker invoker, ObjectName regName, String magicToken) 686 throws MBeanRegistrationException , NotCompliantMBeanException 687 { 688 689 if (regName != null) 692 regName = qualifyName(regName); 693 694 ObjectName mbeanName = null; 696 697 try 698 { 699 mbeanName = invoker.preRegister(server, regName); 702 } 703 catch (NotCompliantMBeanException ncex) 705 { 706 throw ncex; 707 708 } 709 catch (Exception e) 711 { 712 if (e instanceof MBeanRegistrationException ) 713 { 714 throw (MBeanRegistrationException )e; 715 } 716 717 throw new MBeanRegistrationException (e, 718 "preRegister() failed: " + 719 "[ObjectName='" + regName + 720 "', Class=" + invoker.getResource().getClass().getName() + 721 " (" + invoker.getResource() + ")]" 722 ); 723 } 724 catch (Throwable t) 725 { 726 log.warn("preRegister() failed for " + regName + ": ", t); 727 728 if (t instanceof Error ) 729 throw new RuntimeErrorException ((Error )t); 730 else 731 throw new RuntimeException (t.toString()); 732 } 733 734 735 if (regName == null) 738 regName = mbeanName; 739 740 return validateAndQualifyName(regName, magicToken); 741 } 742 743 752 protected synchronized void add(MBeanEntry entry) 753 throws InstanceAlreadyExistsException 754 { 755 ObjectName name = entry.getObjectName(); 757 String domain = name.getDomain(); 758 String props = name.getCanonicalKeyPropertyListString(); 759 760 Map mbeanMap = getMBeanMap(domain, true); 762 763 if (mbeanMap.get(props) != null) 765 throw new InstanceAlreadyExistsException (name + " already registered."); 766 767 mbeanMap.put(props, entry); 769 } 770 771 780 protected synchronized void remove(ObjectName name) 781 throws InstanceNotFoundException 782 { 783 String domain = name.getDomain(); 785 String props = name.getCanonicalKeyPropertyListString(); 786 Map mbeanMap = getMBeanMap(domain, false); 787 788 if (null == mbeanMap || null == mbeanMap.remove(props)) 790 throw new InstanceNotFoundException (name + " not registered."); 791 } 792 793 810 protected ObjectName validateAndQualifyName(ObjectName name, 811 String magicToken) 812 { 813 ObjectName result = qualifyName(name); 815 816 if (result.isPattern()) 818 throw new RuntimeOperationsException ( 819 new IllegalArgumentException ("Object name is a pattern:" + name)); 820 821 if (magicToken != JMI_DOMAIN && 823 result.getDomain().equals(JMI_DOMAIN)) 824 throw new RuntimeOperationsException (new IllegalArgumentException ( 825 "Domain " + JMI_DOMAIN + " is reserved")); 826 827 return result; 829 } 830 831 842 protected ObjectName qualifyName(ObjectName name) 843 { 844 if (name == null) 845 throw new RuntimeOperationsException ( 846 new IllegalArgumentException ("Null object name")); 847 try 848 { 849 if (name.getDomain().length() == 0) 850 return new ObjectName (defaultDomain + ":" + 851 name.getCanonicalKeyPropertyListString()); 852 else 853 return name; 854 } 855 catch (MalformedObjectNameException e) 856 { 857 throw new RuntimeOperationsException ( 858 new IllegalArgumentException (e.toString())); 859 } 860 } 861 862 887 protected void persistIfRequired(MBeanInfo info, ObjectName name) 888 throws 889 MalformedObjectNameException , 890 InstanceNotFoundException , 891 MBeanException , 892 ReflectionException 893 { 894 if(!(info instanceof ModelMBeanInfo )) 895 { 896 return; 897 } 898 ModelMBeanInfo mmbInfo = (ModelMBeanInfo ) info; 899 Descriptor descriptor; 900 try 901 { 902 descriptor = mmbInfo.getMBeanDescriptor(); 903 } 904 catch(MBeanException cause) 905 { 906 log.error("Error trying to get descriptors.", cause); 907 return; 908 } 909 if (descriptor == null) 910 return; 911 String persistInfo = (String ) descriptor.getFieldValue(ModelMBeanConstants.PERSIST_INFO); 912 if (persistInfo == null) 913 return; log.debug("persistInfo: " + persistInfo); 915 Boolean shouldPersist = new Boolean (persistInfo); 916 if(!shouldPersist.booleanValue()) 917 { 918 return; 919 } 920 mbInfosToStore().add(name); 921 if(contains(mbeanInfoService)) 923 { 924 log.debug("flushing queue"); 926 server.invoke( 927 mbeanInfoService, 928 "add", 929 new Object [] { mbInfosToStore().clone() }, 930 new String [] { mbInfosToStore().getClass().getName() }); 931 log.debug("clearing queue"); 932 mbInfosToStore().clear(); 933 } 934 else 935 { 936 log.debug("service is not registered. items remain in queue"); 937 } 938 } 939 940 944 protected Vector mbInfosToStore() 945 { 946 if(fMbInfosToStore == null) 947 { 948 fMbInfosToStore = new Vector (10); 949 } 950 return fMbInfosToStore; 951 } 952 953 963 private Map getMBeanMap(String domain, boolean createIfMissing) 964 { 965 Map mbeanMap = (Map ) domainMap.get(domain); 966 if (mbeanMap == null && createIfMissing) 967 { 968 mbeanMap = new ConcurrentReaderHashMap(); 969 domainMap.put(domain, mbeanMap); 970 } 971 return mbeanMap; 972 } 973 } | Popular Tags |