1 8 9 package mx4j.server; 10 11 import java.io.ByteArrayInputStream ; 12 import java.io.IOException ; 13 import java.io.ObjectInputStream ; 14 import java.security.AccessController ; 15 import java.security.PrivilegedAction ; 16 import java.security.PrivilegedActionException ; 17 import java.security.PrivilegedExceptionAction ; 18 import java.util.HashMap ; 19 import java.util.HashSet ; 20 import java.util.Hashtable ; 21 import java.util.Iterator ; 22 import java.util.Map ; 23 import java.util.Set ; 24 25 import javax.management.Attribute ; 26 import javax.management.AttributeList ; 27 import javax.management.AttributeNotFoundException ; 28 import javax.management.BadAttributeValueExpException ; 29 import javax.management.BadBinaryOpValueExpException ; 30 import javax.management.BadStringOperationException ; 31 import javax.management.InstanceAlreadyExistsException ; 32 import javax.management.InstanceNotFoundException ; 33 import javax.management.IntrospectionException ; 34 import javax.management.InvalidApplicationException ; 35 import javax.management.InvalidAttributeValueException ; 36 import javax.management.JMRuntimeException ; 37 import javax.management.ListenerNotFoundException ; 38 import javax.management.MBeanException ; 39 import javax.management.MBeanInfo ; 40 import javax.management.MBeanPermission ; 41 import javax.management.MBeanRegistrationException ; 42 import javax.management.MBeanServer ; 43 import javax.management.MBeanServerDelegate ; 44 import javax.management.MBeanServerNotification ; 45 import javax.management.MBeanServerPermission ; 46 import javax.management.MalformedObjectNameException ; 47 import javax.management.NotCompliantMBeanException ; 48 import javax.management.NotificationBroadcaster ; 49 import javax.management.NotificationEmitter ; 50 import javax.management.NotificationFilter ; 51 import javax.management.NotificationListener ; 52 import javax.management.ObjectInstance ; 53 import javax.management.ObjectName ; 54 import javax.management.OperationsException ; 55 import javax.management.QueryExp ; 56 import javax.management.ReflectionException ; 57 import javax.management.RuntimeOperationsException ; 58 import javax.management.loading.ClassLoaderRepository ; 59 import javax.management.loading.PrivateClassLoader ; 60 61 import mx4j.ImplementationException; 62 import mx4j.MX4JSystemKeys; 63 import mx4j.loading.ClassLoaderObjectInputStream; 64 import mx4j.log.Log; 65 import mx4j.log.Logger; 66 import mx4j.server.interceptor.ContextClassLoaderMBeanServerInterceptor; 67 import mx4j.server.interceptor.InvokerMBeanServerInterceptor; 68 import mx4j.server.interceptor.MBeanServerInterceptor; 69 import mx4j.server.interceptor.MBeanServerInterceptorConfigurator; 70 import mx4j.server.interceptor.NotificationListenerMBeanServerInterceptor; 71 import mx4j.server.interceptor.SecurityMBeanServerInterceptor; 72 import mx4j.util.Utils; 73 74 97 public class MX4JMBeanServer implements MBeanServer  98 { 99 private String defaultDomain; 100 private MBeanRepository mbeanRepository; 101 private MBeanServerDelegate delegate; 102 private ObjectName delegateName; 103 private MBeanIntrospector introspector; 104 private MBeanServerInterceptorConfigurator invoker; 105 private static long notifications; 106 private ModifiableClassLoaderRepository classLoaderRepository; 107 private Map domains = new HashMap (); 108 109 private static final String [] EMPTY_PARAMS = new String [0]; 110 private static final Object [] EMPTY_ARGS = new Object [0]; 111 112 119 public MX4JMBeanServer(String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate) 120 { 121 Logger logger = getLogger(); 122 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Creating MBeanServer instance..."); 123 124 SecurityManager sm = System.getSecurityManager(); 125 if (sm != null) 126 { 127 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Checking permission to create MBeanServer..."); 128 sm.checkPermission(new MBeanServerPermission ("newMBeanServer")); 129 } 130 131 if (defaultDomain == null) defaultDomain = "DefaultDomain"; 132 this.defaultDomain = defaultDomain; 133 134 if (delegate == null) throw new JMRuntimeException ("Delegate can't be null"); 135 this.delegate = delegate; 136 137 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("MBeanServer default domain is: '" + this.defaultDomain + "'"); 138 139 mbeanRepository = createMBeanRepository(); 140 141 classLoaderRepository = createClassLoaderRepository(); 142 classLoaderRepository.addClassLoader(getClass().getClassLoader()); 144 classLoaderRepository.addClassLoader(ClassLoader.getSystemClassLoader()); 146 147 introspector = new MBeanIntrospector(); 148 149 try 151 { 152 delegateName = new ObjectName ("JMImplementation", "type", "MBeanServerDelegate"); 153 } 154 catch (MalformedObjectNameException ignored) 155 { 156 } 157 158 try 159 { 160 ObjectName invokerName = new ObjectName (MBeanServerInterceptorConfigurator.OBJECT_NAME); 161 invoker = new MBeanServerInterceptorConfigurator(this); 162 163 ContextClassLoaderMBeanServerInterceptor ccl = new ContextClassLoaderMBeanServerInterceptor(); 164 NotificationListenerMBeanServerInterceptor notif = new NotificationListenerMBeanServerInterceptor(); 165 SecurityMBeanServerInterceptor sec = new SecurityMBeanServerInterceptor(); 166 InvokerMBeanServerInterceptor inv = new InvokerMBeanServerInterceptor(outer == null ? this : outer); 167 168 invoker.addPreInterceptor(ccl); 169 invoker.addPreInterceptor(notif); 170 invoker.addPreInterceptor(sec); 171 invoker.addPostInterceptor(inv); 172 invoker.start(); 173 174 privilegedRegisterMBean(invoker, invokerName); 176 177 ObjectName cclName = new ObjectName ("JMImplementation", "interceptor", "contextclassloader"); 178 ObjectName notifName = new ObjectName ("JMImplementation", "interceptor", "notificationwrapper"); 179 ObjectName secName = new ObjectName ("JMImplementation", "interceptor", "security"); 180 ObjectName invName = new ObjectName ("JMImplementation", "interceptor", "invoker"); 181 182 privilegedRegisterMBean(ccl, cclName); 183 privilegedRegisterMBean(notif, notifName); 184 privilegedRegisterMBean(sec, secName); 185 privilegedRegisterMBean(inv, invName); 186 } 187 catch (Exception x) 188 { 189 logger.error("MBeanServerInterceptorConfigurator cannot be registered", x); 190 throw new ImplementationException(); 191 } 192 193 try 195 { 196 privilegedRegisterMBean(delegate, delegateName); 197 } 198 catch (Exception x) 199 { 200 logger.error("MBeanServerDelegate cannot be registered", x); 201 throw new ImplementationException(x.toString()); 202 } 203 204 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("MBeanServer instance created successfully"); 205 } 206 207 214 public ClassLoaderRepository getClassLoaderRepository() 215 { 216 SecurityManager sm = System.getSecurityManager(); 217 if (sm != null) 218 { 219 sm.checkPermission(new MBeanPermission ("-#-[-]", "getClassLoaderRepository")); 220 } 221 222 return getModifiableClassLoaderRepository(); 223 } 224 225 private ModifiableClassLoaderRepository getModifiableClassLoaderRepository() 226 { 227 return classLoaderRepository; 228 } 229 230 public ClassLoader getClassLoader(ObjectName name) throws InstanceNotFoundException  231 { 232 SecurityManager sm = System.getSecurityManager(); 233 if (sm != null) 234 { 235 name = secureObjectName(name); 236 237 if (name == null) 238 { 239 sm.checkPermission(new MBeanPermission ("-#-[-]", "getClassLoader")); 240 } 241 else 242 { 243 MBeanMetaData metadata = findMBeanMetaData(name); 244 sm.checkPermission(new MBeanPermission (metadata.getMBeanInfo().getClassName(), "-", name, "getClassLoader")); 245 } 246 } 247 248 return getClassLoaderImpl(name); 249 } 250 251 public ClassLoader getClassLoaderFor(ObjectName name) throws InstanceNotFoundException  252 { 253 SecurityManager sm = System.getSecurityManager(); 254 if (sm != null) 255 { 256 name = secureObjectName(name); 257 } 258 259 MBeanMetaData metadata = findMBeanMetaData(name); 261 262 if (sm != null) 263 { 264 sm.checkPermission(new MBeanPermission (metadata.getMBeanInfo().getClassName(), "-", name, "getClassLoaderFor")); 265 } 266 267 return metadata.getMBean().getClass().getClassLoader(); 268 } 269 270 274 private ClassLoader getClassLoaderImpl(ObjectName name) throws InstanceNotFoundException  275 { 276 if (name == null) 277 { 278 return getClass().getClassLoader(); 279 } 280 else 281 { 282 MBeanMetaData metadata = findMBeanMetaData(name); 283 if (metadata.getMBean() instanceof ClassLoader ) 284 { 285 return (ClassLoader )metadata.getMBean(); 286 } 287 else 288 { 289 throw new InstanceNotFoundException (name.getCanonicalName()); 290 } 291 } 292 } 293 294 public ObjectInputStream deserialize(String className, ObjectName loaderName, byte[] bytes) 295 throws InstanceNotFoundException , OperationsException , ReflectionException  296 { 297 if (className == null || className.trim().length() == 0) 298 { 299 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid class name '" + className + "'")); 300 } 301 302 ClassLoader cl = getClassLoader(loaderName); 303 304 try 305 { 306 Class cls = cl.loadClass(className); 307 return deserializeImpl(cls.getClassLoader(), bytes); 308 } 309 catch (ClassNotFoundException x) 310 { 311 throw new ReflectionException (x); 312 } 313 } 314 315 public ObjectInputStream deserialize(String className, byte[] bytes) 316 throws OperationsException , ReflectionException  317 { 318 if (className == null || className.trim().length() == 0) 319 { 320 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid class name '" + className + "'")); 321 } 322 323 try 325 { 326 Class cls = getClassLoaderRepository().loadClass(className); 327 return deserializeImpl(cls.getClassLoader(), bytes); 328 } 329 catch (ClassNotFoundException x) 330 { 331 throw new ReflectionException (x); 332 } 333 } 334 335 public ObjectInputStream deserialize(ObjectName objectName, byte[] bytes) 336 throws InstanceNotFoundException , OperationsException  337 { 338 ClassLoader cl = getClassLoaderFor(objectName); 339 return deserializeImpl(cl, bytes); 340 } 341 342 345 private ObjectInputStream deserializeImpl(ClassLoader classloader, byte[] bytes) throws OperationsException  346 { 347 if (bytes == null || bytes.length == 0) 348 { 349 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid byte array " + bytes)); 350 } 351 352 ByteArrayInputStream bais = new ByteArrayInputStream (bytes); 353 try 354 { 355 return new ClassLoaderObjectInputStream(bais, classloader); 356 } 357 catch (IOException x) 358 { 359 throw new OperationsException (x.toString()); 360 } 361 } 362 363 private MBeanServerInterceptor getHeadInterceptor() 364 { 365 MBeanServerInterceptor head = invoker.getHeadInterceptor(); 366 367 if (head == null) throw new IllegalStateException ("No MBeanServer interceptor, probably the configurator has been stopped"); 368 369 return head; 370 } 371 372 private Logger getLogger() 373 { 374 return Log.getLogger(getClass().getName()); 375 } 376 377 384 private MBeanRepository createMBeanRepository() 385 { 386 Logger logger = getLogger(); 387 388 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Checking for system property " + MX4JSystemKeys.MX4J_MBEANSERVER_REPOSITORY); 389 390 String value = (String )AccessController.doPrivileged(new PrivilegedAction () 391 { 392 public Object run() 393 { 394 return System.getProperty(MX4JSystemKeys.MX4J_MBEANSERVER_REPOSITORY); 395 } 396 }); 397 398 if (value != null) 399 { 400 if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Property found for custom MBeanServer registry; class is: " + value); 401 402 try 403 { 404 MBeanRepository registry = (MBeanRepository)Thread.currentThread().getContextClassLoader().loadClass(value).newInstance(); 405 if (logger.isEnabledFor(Logger.TRACE)) 406 { 407 logger.trace("Custom MBeanServer registry created successfully"); 408 } 409 return registry; 410 } 411 catch (Exception x) 412 { 413 if (logger.isEnabledFor(Logger.TRACE)) 414 { 415 logger.trace("Custom MBeanServer registry could not be created", x); 416 } 417 } 418 } 419 420 return new DefaultMBeanRepository(); 421 } 422 423 431 private ModifiableClassLoaderRepository createClassLoaderRepository() 432 { 433 Logger logger = getLogger(); 434 435 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Checking for system property " + MX4JSystemKeys.MX4J_MBEANSERVER_CLASSLOADER_REPOSITORY); 436 437 String value = (String )AccessController.doPrivileged(new PrivilegedAction () 438 { 439 public Object run() 440 { 441 return System.getProperty(MX4JSystemKeys.MX4J_MBEANSERVER_CLASSLOADER_REPOSITORY); 442 } 443 }); 444 445 if (value != null) 446 { 447 if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Property found for custom ClassLoaderRepository; class is: " + value); 448 449 try 450 { 451 ModifiableClassLoaderRepository repository = (ModifiableClassLoaderRepository)Thread.currentThread().getContextClassLoader().loadClass(value).newInstance(); 452 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Custom ClassLoaderRepository created successfully " + repository); 453 return repository; 454 } 455 catch (Exception x) 456 { 457 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Custom ClassLoaderRepository could not be created", x); 458 } 459 } 460 return new DefaultClassLoaderRepository(); 461 } 462 463 466 private MBeanRepository getMBeanRepository() 467 { 468 return mbeanRepository; 469 } 470 471 476 private MBeanMetaData findMBeanMetaData(ObjectName objectName) throws InstanceNotFoundException  477 { 478 MBeanMetaData metadata = null; 479 if (objectName != null) 480 { 481 objectName = normalizeObjectName(objectName); 482 483 MBeanRepository repository = getMBeanRepository(); 484 synchronized (repository) 485 { 486 metadata = repository.get(objectName); 487 } 488 } 489 if (metadata == null) 490 { 491 throw new InstanceNotFoundException ("MBeanServer cannot find MBean with ObjectName " + objectName); 492 } 493 return metadata; 494 } 495 496 public void addNotificationListener(ObjectName observed, ObjectName listener, NotificationFilter filter, Object handback) 497 throws InstanceNotFoundException  498 { 499 listener = secureObjectName(listener); 500 501 Object mbean = findMBeanMetaData(listener).getMBean(); 502 if (!(mbean instanceof NotificationListener )) 503 { 504 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean " + listener + " is not a NotificationListener")); 505 } 506 addNotificationListener(observed, (NotificationListener )mbean, filter, handback); 507 } 508 509 public void addNotificationListener(ObjectName observed, NotificationListener listener, NotificationFilter filter, Object handback) 510 throws InstanceNotFoundException  511 { 512 if (observed == null) 513 { 514 throw new RuntimeOperationsException (new IllegalArgumentException ("ObjectName cannot be null")); 515 } 516 if (listener == null) 517 { 518 throw new RuntimeOperationsException (new IllegalArgumentException ("NotificationListener cannot be null")); 519 } 520 521 observed = secureObjectName(observed); 522 523 MBeanMetaData metadata = findMBeanMetaData(observed); 524 525 Object mbean = metadata.getMBean(); 526 527 if (!(mbean instanceof NotificationBroadcaster )) 528 { 529 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean " + observed + " is not a NotificationBroadcaster")); 530 } 531 532 addNotificationListenerImpl(metadata, listener, filter, handback); 533 } 534 535 private void addNotificationListenerImpl(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback) 536 { 537 getHeadInterceptor().addNotificationListener(metadata, listener, filter, handback); 538 } 539 540 public void removeNotificationListener(ObjectName observed, ObjectName listener) 541 throws InstanceNotFoundException , ListenerNotFoundException  542 { 543 listener = secureObjectName(listener); 544 545 Object mbean = findMBeanMetaData(listener).getMBean(); 546 if (!(mbean instanceof NotificationListener )) 547 { 548 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean " + listener + " is not a NotificationListener")); 549 } 550 removeNotificationListener(observed, (NotificationListener )mbean); 551 } 552 553 public void removeNotificationListener(ObjectName observed, NotificationListener listener) 554 throws InstanceNotFoundException , ListenerNotFoundException  555 { 556 if (listener == null) 557 { 558 throw new ListenerNotFoundException ("NotificationListener cannot be null"); 559 } 560 561 observed = secureObjectName(observed); 562 563 MBeanMetaData metadata = findMBeanMetaData(observed); 564 Object mbean = metadata.getMBean(); 565 566 if (!(mbean instanceof NotificationBroadcaster )) 567 { 568 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean " + observed + " is not a NotificationBroadcaster")); 569 } 570 571 removeNotificationListenerImpl(metadata, listener); 572 } 573 574 public void removeNotificationListener(ObjectName observed, ObjectName listener, NotificationFilter filter, Object handback) 575 throws InstanceNotFoundException , ListenerNotFoundException  576 { 577 listener = secureObjectName(listener); 578 579 Object mbean = findMBeanMetaData(listener).getMBean(); 580 if (!(mbean instanceof NotificationListener )) 581 { 582 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean " + listener + " is not a NotificationListener")); 583 } 584 removeNotificationListener(observed, (NotificationListener )mbean, filter, handback); 585 } 586 587 public void removeNotificationListener(ObjectName observed, NotificationListener listener, NotificationFilter filter, Object handback) 588 throws InstanceNotFoundException , ListenerNotFoundException  589 { 590 if (listener == null) 591 { 592 throw new ListenerNotFoundException ("NotificationListener cannot be null"); 593 } 594 595 observed = secureObjectName(observed); 596 597 MBeanMetaData metadata = findMBeanMetaData(observed); 598 Object mbean = metadata.getMBean(); 599 600 if (!(mbean instanceof NotificationEmitter )) 601 { 602 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean " + observed + " is not a NotificationEmitter")); 603 } 604 605 removeNotificationListenerImpl(metadata, listener, filter, handback); 606 } 607 608 private void removeNotificationListenerImpl(MBeanMetaData metadata, NotificationListener listener) 609 throws ListenerNotFoundException  610 { 611 getHeadInterceptor().removeNotificationListener(metadata, listener); 612 } 613 614 private void removeNotificationListenerImpl(MBeanMetaData metadata, NotificationListener listener, NotificationFilter filter, Object handback) 615 throws ListenerNotFoundException  616 { 617 getHeadInterceptor().removeNotificationListener(metadata, listener, filter, handback); 618 } 619 620 public Object instantiate(String className) 621 throws ReflectionException , MBeanException  622 { 623 return instantiate(className, null, null); 624 } 625 626 public Object instantiate(String className, Object [] args, String [] parameters) 627 throws ReflectionException , MBeanException  628 { 629 if (className == null || className.trim().length() == 0) 630 { 631 throw new RuntimeOperationsException (new IllegalArgumentException ("Class name cannot be null or empty")); 632 } 633 634 try 635 { 636 Class cls = getModifiableClassLoaderRepository().loadClass(className); 637 return instantiateImpl(className, cls.getClassLoader(), null, parameters, args).getMBean(); 638 } 639 catch (ClassNotFoundException x) 640 { 641 throw new ReflectionException (x); 642 } 643 } 644 645 public Object instantiate(String className, ObjectName loaderName) 646 throws ReflectionException , MBeanException , InstanceNotFoundException  647 { 648 return instantiate(className, loaderName, null, null); 649 } 650 651 public Object instantiate(String className, ObjectName loaderName, Object [] args, String [] parameters) 652 throws ReflectionException , MBeanException , InstanceNotFoundException  653 { 654 if (className == null || className.trim().length() == 0) 655 { 656 throw new RuntimeOperationsException (new IllegalArgumentException ("Class name cannot be null or empty")); 657 } 658 659 661 loaderName = secureObjectName(loaderName); 662 if (loaderName != null && loaderName.isPattern()) 663 { 664 throw new RuntimeOperationsException (new IllegalArgumentException ("ObjectName for the ClassLoader cannot be a pattern ObjectName: " + loaderName)); 665 } 666 667 ClassLoader cl = getClassLoaderImpl(loaderName); 668 return instantiateImpl(className, cl, null, parameters, args).getMBean(); 669 } 670 671 private MBeanMetaData instantiateImpl(String className, ClassLoader classloader, ObjectName name, String [] params, Object [] args) 672 throws ReflectionException , MBeanException  673 { 674 if (params == null) params = EMPTY_PARAMS; 675 if (args == null) args = EMPTY_ARGS; 676 677 MBeanMetaData metadata = createMBeanMetaData(); 678 metadata.setClassLoader(classloader); 679 metadata.setObjectName(secureObjectName(name)); 680 681 getHeadInterceptor().instantiate(metadata, className, params, args); 682 683 return metadata; 684 } 685 686 public ObjectInstance createMBean(String className, ObjectName objectName) 687 throws ReflectionException , InstanceAlreadyExistsException , MBeanRegistrationException , MBeanException , NotCompliantMBeanException  688 { 689 return createMBean(className, objectName, null, null); 690 } 691 692 public ObjectInstance createMBean(String className, ObjectName objectName, Object [] args, String [] parameters) 693 throws ReflectionException , InstanceAlreadyExistsException , MBeanRegistrationException , MBeanException , NotCompliantMBeanException  694 { 695 try 696 { 697 Class cls = getModifiableClassLoaderRepository().loadClass(className); 698 MBeanMetaData metadata; 699 700 try 704 { 705 metadata = instantiateImpl(className, cls.getClassLoader(), objectName, parameters, args); 706 } 707 catch (ReflectionException e) 708 { 709 Exception target = e.getTargetException(); 710 if (target instanceof InstantiationException ) 711 { 712 throw new NotCompliantMBeanException (); 713 } 714 else 715 { 716 throw e; 717 } 718 } 719 720 registerImpl(metadata, false); 721 722 return metadata.getObjectInstance(); 723 } 724 catch (ClassNotFoundException x) 725 { 726 throw new ReflectionException (x); 727 } 728 } 729 730 public ObjectInstance createMBean(String className, ObjectName objectName, ObjectName loaderName) 731 throws ReflectionException , InstanceAlreadyExistsException , MBeanRegistrationException , MBeanException , NotCompliantMBeanException , InstanceNotFoundException  732 { 733 return createMBean(className, objectName, loaderName, null, null); 734 } 735 736 public ObjectInstance createMBean(String className, ObjectName objectName, ObjectName loaderName, Object [] args, String [] parameters) 737 throws ReflectionException , InstanceAlreadyExistsException , MBeanRegistrationException , MBeanException , NotCompliantMBeanException , InstanceNotFoundException  738 { 739 loaderName = secureObjectName(loaderName); 740 741 ClassLoader cl = getClassLoaderImpl(loaderName); 742 743 MBeanMetaData metadata = instantiateImpl(className, cl, objectName, parameters, args); 744 745 registerImpl(metadata, false); 746 747 return metadata.getObjectInstance(); 748 } 749 750 public ObjectInstance registerMBean(Object mbean, ObjectName objectName) 751 throws InstanceAlreadyExistsException , MBeanRegistrationException , NotCompliantMBeanException  752 { 753 return registerMBeanImpl(mbean, objectName, false); 754 } 755 756 private ObjectInstance registerMBeanImpl(Object mbean, ObjectName objectName, boolean privileged) 757 throws InstanceAlreadyExistsException , MBeanRegistrationException , NotCompliantMBeanException  758 { 759 if (mbean == null) 760 { 761 throw new RuntimeOperationsException (new IllegalArgumentException ("MBean instance cannot be null")); 762 } 763 764 MBeanMetaData metadata = createMBeanMetaData(); 765 metadata.setMBean(mbean); 766 metadata.setClassLoader(mbean.getClass().getClassLoader()); 767 metadata.setObjectName(secureObjectName(objectName)); 768 769 registerImpl(metadata, privileged); 770 771 return metadata.getObjectInstance(); 772 } 773 774 777 private MBeanMetaData createMBeanMetaData() 778 { 779 return MBeanMetaData.Factory.create(); 780 } 781 782 787 private ObjectInstance privilegedRegisterMBean(final Object mbean, final ObjectName name) 788 throws InstanceAlreadyExistsException , MBeanRegistrationException , NotCompliantMBeanException  789 { 790 try 791 { 792 return (ObjectInstance )AccessController.doPrivileged(new PrivilegedExceptionAction () 793 { 794 public Object run() throws Exception  795 { 796 return registerMBeanImpl(mbean, name, true); 797 } 798 }); 799 } 800 catch (PrivilegedActionException x) 801 { 802 Exception xx = x.getException(); 803 if (xx instanceof InstanceAlreadyExistsException ) 804 throw (InstanceAlreadyExistsException )xx; 805 else if (xx instanceof MBeanRegistrationException ) 806 throw (MBeanRegistrationException )xx; 807 else if (xx instanceof NotCompliantMBeanException ) 808 throw (NotCompliantMBeanException )xx; 809 else 810 throw new MBeanRegistrationException (xx); 811 } 812 } 813 814 private void registerImpl(MBeanMetaData metadata, boolean privileged) throws InstanceAlreadyExistsException , MBeanRegistrationException , NotCompliantMBeanException  815 { 816 introspector.introspect(metadata); 817 818 if (!introspector.isMBeanCompliant(metadata)) throw new NotCompliantMBeanException ("MBean is not compliant"); 819 820 MBeanServerInterceptor head = getHeadInterceptor(); 821 822 head.registration(metadata, MBeanServerInterceptor.PRE_REGISTER); 823 824 metadata.setObjectName(secureObjectName(metadata.getObjectName())); 826 827 int postRegisterFlag = MBeanServerInterceptor.POST_REGISTER_FALSE; 828 try 829 { 830 register(metadata, privileged); 831 postRegisterFlag = MBeanServerInterceptor.POST_REGISTER_TRUE; 832 } 833 finally 834 { 835 head.registration(metadata, postRegisterFlag); 836 } 837 838 Object mbean = metadata.getMBean(); 839 if (mbean instanceof ClassLoader && !(mbean instanceof PrivateClassLoader )) 840 { 841 ClassLoader cl = (ClassLoader )mbean; 842 getModifiableClassLoaderRepository().addClassLoader(cl); 843 } 844 } 845 846 private void register(MBeanMetaData metadata, boolean privileged) throws InstanceAlreadyExistsException  847 { 848 metadata.setObjectName(normalizeObjectName(metadata.getObjectName())); 849 850 ObjectName objectName = metadata.getObjectName(); 851 if (objectName == null || objectName.isPattern()) 852 { 853 throw new RuntimeOperationsException (new IllegalArgumentException ("ObjectName cannot be null or a pattern ObjectName")); 854 } 855 if (objectName.getDomain().equals("JMImplementation") && !privileged) 856 { 857 throw new JMRuntimeException ("Domain 'JMImplementation' is reserved for the JMX Agent"); 858 } 859 860 MBeanRepository repository = getMBeanRepository(); 861 synchronized (repository) 862 { 863 if (repository.get(objectName) != null) throw new InstanceAlreadyExistsException (objectName.toString()); 864 865 repository.put(objectName, metadata); 866 } 867 addDomain(objectName.getDomain()); 868 869 notify(objectName, MBeanServerNotification.REGISTRATION_NOTIFICATION); 870 } 871 872 private void notify(ObjectName objectName, String notificationType) 873 { 874 long sequenceNumber = 0; 875 synchronized (MX4JMBeanServer.class) 876 { 877 sequenceNumber = notifications; 878 ++notifications; 879 } 880 881 delegate.sendNotification(new MBeanServerNotification (notificationType, delegateName, sequenceNumber, objectName)); 882 } 883 884 private void addDomain(String domain) 885 { 886 synchronized (domains) 887 { 888 Integer count = (Integer )domains.get(domain); 889 if (count == null) 890 domains.put(domain, new Integer (1)); 891 else 892 domains.put(domain, new Integer (count.intValue() + 1)); 893 } 894 } 895 896 private void removeDomain(String domain) 897 { 898 synchronized (domains) 899 { 900 Integer count = (Integer )domains.get(domain); 901 if (count == null) throw new ImplementationException(); 902 if (count.intValue() < 2) 903 domains.remove(domain); 904 else 905 domains.put(domain, new Integer (count.intValue() - 1)); 906 } 907 } 908 909 public void unregisterMBean(ObjectName objectName) 910 throws InstanceNotFoundException , MBeanRegistrationException  911 { 912 objectName = secureObjectName(objectName); 913 914 if (objectName == null || objectName.isPattern()) 915 { 916 throw new RuntimeOperationsException (new IllegalArgumentException ("ObjectName cannot be null or a pattern ObjectName")); 917 } 918 919 if (objectName.getDomain().equals("JMImplementation")) 920 { 921 throw new RuntimeOperationsException (new IllegalArgumentException ("Domain 'JMImplementation' is reserved for the JMX Agent")); 922 } 923 924 MBeanMetaData metadata = findMBeanMetaData(objectName); 925 926 MBeanServerInterceptor head = getHeadInterceptor(); 927 head.registration(metadata, MBeanServerInterceptor.PRE_DEREGISTER); 928 unregister(metadata); 929 930 getHeadInterceptor().registration(metadata, MBeanServerInterceptor.POST_DEREGISTER); 931 932 Object mbean = metadata.getMBean(); 933 if (mbean instanceof ClassLoader && !(mbean instanceof PrivateClassLoader )) 934 { 935 getModifiableClassLoaderRepository().removeClassLoader((ClassLoader )mbean); 936 } 937 } 938 939 private void unregister(MBeanMetaData metadata) 940 { 941 ObjectName objectName = metadata.getObjectName(); 942 943 MBeanRepository repository = getMBeanRepository(); 944 synchronized (repository) 945 { 946 repository.remove(objectName); 947 } 948 removeDomain(objectName.getDomain()); 949 950 notify(objectName, MBeanServerNotification.UNREGISTRATION_NOTIFICATION); 951 } 952 953 public Object getAttribute(ObjectName objectName, String attribute) 954 throws InstanceNotFoundException , MBeanException , AttributeNotFoundException , ReflectionException  955 { 956 if (attribute == null || attribute.trim().length() == 0) 957 { 958 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid attribute")); 959 } 960 961 objectName = secureObjectName(objectName); 962 963 MBeanMetaData metadata = findMBeanMetaData(objectName); 964 965 return getHeadInterceptor().getAttribute(metadata, attribute); 966 } 967 968 969 public void setAttribute(ObjectName objectName, Attribute attribute) 970 throws InstanceNotFoundException , AttributeNotFoundException , InvalidAttributeValueException , MBeanException , ReflectionException  971 { 972 if (attribute == null || attribute.getName().trim().length() == 0) 973 { 974 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid attribute")); 975 } 976 977 objectName = secureObjectName(objectName); 978 979 MBeanMetaData metadata = findMBeanMetaData(objectName); 980 981 getHeadInterceptor().setAttribute(metadata, attribute); 982 } 983 984 public AttributeList getAttributes(ObjectName objectName, String [] attributes) 985 throws InstanceNotFoundException , ReflectionException  986 { 987 if (attributes == null) 988 { 989 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid attribute list")); 990 } 991 992 objectName = secureObjectName(objectName); 993 994 MBeanMetaData metadata = findMBeanMetaData(objectName); 995 996 SecurityManager sm = System.getSecurityManager(); 997 if (sm != null) 998 { 999 sm.checkPermission(new MBeanPermission (metadata.getMBeanInfo().getClassName(), "-", objectName, "getAttribute")); 1001 } 1002 1003 return getHeadInterceptor().getAttributes(metadata, attributes); 1004 } 1005 1006 public AttributeList setAttributes(ObjectName objectName, AttributeList attributes) 1007 throws InstanceNotFoundException , ReflectionException  1008 { 1009 if (attributes == null) 1010 { 1011 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid attribute list")); 1012 } 1013 1014 objectName = secureObjectName(objectName); 1015 1016 MBeanMetaData metadata = findMBeanMetaData(objectName); 1017 1018 SecurityManager sm = System.getSecurityManager(); 1019 if (sm != null) 1020 { 1021 sm.checkPermission(new MBeanPermission (metadata.getMBeanInfo().getClassName(), "-", objectName, "setAttribute")); 1023 } 1024 1025 return getHeadInterceptor().setAttributes(metadata, attributes); 1026 } 1027 1028 public Object invoke(ObjectName objectName, String methodName, Object [] args, String [] parameters) 1029 throws InstanceNotFoundException , MBeanException , ReflectionException  1030 { 1031 if (methodName == null || methodName.trim().length() == 0) 1032 { 1033 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid operation name '" + methodName + "'")); 1034 } 1035 1036 if (args == null) args = EMPTY_ARGS; 1037 if (parameters == null) parameters = EMPTY_PARAMS; 1038 1039 objectName = secureObjectName(objectName); 1040 1041 MBeanMetaData metadata = findMBeanMetaData(objectName); 1042 1043 return getHeadInterceptor().invoke(metadata, methodName, parameters, args); 1044 } 1045 1046 public String getDefaultDomain() 1047 { 1048 return defaultDomain; 1049 } 1050 1051 public String [] getDomains() 1052 { 1053 SecurityManager sm = System.getSecurityManager(); 1054 if (sm != null) 1055 { 1056 sm.checkPermission(new MBeanPermission (null, null, null, "getDomains")); 1057 } 1058 Set keys; 1059 synchronized (domains) 1060 { 1061 keys = new HashSet (domains.keySet()); 1062 } 1063 if (sm != null) 1064 { 1065 for (Iterator i = keys.iterator(); i.hasNext();) 1066 { 1067 String domain = (String )i.next(); 1068 try 1069 { 1070 ObjectName name = new ObjectName (domain, "x", "x"); 1071 sm.checkPermission(new MBeanPermission (null, null, name, "getDomains")); 1072 } 1073 catch (SecurityException e) 1074 { 1075 i.remove(); 1076 continue; 1077 } 1078 catch (MalformedObjectNameException e) 1079 { 1080 throw new ImplementationException("Unexpected MalformedObjectNameException for registered domain: " + domain); 1081 } 1082 } 1083 } 1084 return (String [])keys.toArray(new String [keys.size()]); 1085 } 1086 1087 public Integer getMBeanCount() 1088 { 1089 MBeanRepository repository = getMBeanRepository(); 1090 synchronized (repository) 1091 { 1092 return new Integer (repository.size()); 1093 } 1094 } 1095 1096 public boolean isRegistered(ObjectName objectName) 1097 { 1098 try 1099 { 1100 return findMBeanMetaData(objectName) != null; 1101 } 1102 catch (InstanceNotFoundException x) 1103 { 1104 return false; 1105 } 1106 } 1107 1108 public MBeanInfo getMBeanInfo(ObjectName objectName) 1109 throws InstanceNotFoundException , IntrospectionException , ReflectionException  1110 { 1111 objectName = secureObjectName(objectName); 1112 1113 MBeanMetaData metadata = findMBeanMetaData(objectName); 1114 1115 MBeanInfo info = getHeadInterceptor().getMBeanInfo(metadata); 1116 if (info == null) throw new JMRuntimeException ("MBeanInfo returned for MBean " + objectName + " is null"); 1117 return info; 1118 } 1119 1120 public ObjectInstance getObjectInstance(ObjectName objectName) 1121 throws InstanceNotFoundException  1122 { 1123 SecurityManager sm = System.getSecurityManager(); 1124 if (sm != null) 1125 { 1126 objectName = secureObjectName(objectName); 1127 } 1128 1129 MBeanMetaData metadata = findMBeanMetaData(objectName); 1130 1131 if (sm != null) 1132 { 1133 sm.checkPermission(new MBeanPermission (metadata.getMBeanInfo().getClassName(), "-", objectName, "getObjectInstance")); 1134 } 1135 1136 return metadata.getObjectInstance(); 1137 } 1138 1139 public boolean isInstanceOf(ObjectName objectName, String className) 1140 throws InstanceNotFoundException  1141 { 1142 if (className == null || className.trim().length() == 0) 1143 { 1144 throw new RuntimeOperationsException (new IllegalArgumentException ("Invalid class name")); 1145 } 1146 1147 objectName = secureObjectName(objectName); 1148 1149 MBeanMetaData metadata = findMBeanMetaData(objectName); 1150 String infoClassName = metadata.getMBeanInfo().getClassName(); 1151 1152 SecurityManager sm = System.getSecurityManager(); 1153 if (sm != null) 1154 { 1155 sm.checkPermission(new MBeanPermission (infoClassName, "-", objectName, "isInstanceOf")); 1156 } 1157 if (className.equals(infoClassName)) return true; 1158 1159 try 1160 { 1161 ClassLoader loader = metadata.getClassLoader(); 1162 if (loader == null) loader = Thread.currentThread().getContextClassLoader(); 1163 Class cls = loader.loadClass(className); 1164 Class infoClass = loader.loadClass(infoClassName); 1165 return cls.isAssignableFrom(infoClass); 1166 } 1167 catch (ClassNotFoundException x) 1168 { 1169 return false; 1170 } 1171 } 1172 1173 public Set queryMBeans(ObjectName patternName, QueryExp filter) 1174 { 1175 SecurityManager sm = System.getSecurityManager(); 1176 if (sm != null) 1177 { 1178 patternName = secureObjectName(patternName); 1179 sm.checkPermission(new MBeanPermission ("-#-[-]", "queryMBeans")); 1182 } 1183 1184 Set match = queryObjectNames(patternName, filter, true); 1185 1186 Set set = new HashSet (); 1187 for (Iterator i = match.iterator(); i.hasNext();) 1188 { 1189 ObjectName name = (ObjectName )i.next(); 1190 try 1191 { 1192 MBeanMetaData metadata = findMBeanMetaData(name); 1193 set.add(metadata.getObjectInstance()); 1194 } 1195 catch (InstanceNotFoundException ignored) 1196 { 1197 } 1199 } 1200 return set; 1201 } 1202 1203 public Set queryNames(ObjectName patternName, QueryExp filter) 1204 { 1205 SecurityManager sm = System.getSecurityManager(); 1206 if (sm != null) 1207 { 1208 patternName = secureObjectName(patternName); 1209 sm.checkPermission(new MBeanPermission ("-#-[-]", "queryNames")); 1212 } 1213 1214 return queryObjectNames(patternName, filter, false); 1215 } 1216 1217 1225 private Set queryObjectNames(ObjectName patternName, QueryExp filter, boolean instances) 1226 { 1227 Set scope = findMBeansByPattern(patternName); 1229 1230 Set secureScope = filterMBeansBySecurity(scope, instances); 1232 1233 Set match = filterMBeansByQuery(secureScope, filter); 1235 1236 return match; 1237 } 1238 1239 1242 private Set findMBeansByPattern(ObjectName pattern) 1243 { 1244 if (pattern == null) 1245 { 1246 try 1247 { 1248 pattern = new ObjectName ("*:*"); 1249 } 1250 catch (MalformedObjectNameException ignored) 1251 { 1252 } 1253 } 1254 1255 pattern = normalizeObjectName(pattern); 1256 1257 String patternDomain = pattern.getDomain(); 1258 Hashtable patternProps = pattern.getKeyPropertyList(); 1259 1260 Set set = new HashSet (); 1261 1262 MBeanRepository repository = null; 1264 MBeanRepository original = getMBeanRepository(); 1265 synchronized (original) 1266 { 1267 repository = (MBeanRepository)original.clone(); 1268 } 1269 1270 for (Iterator i = repository.iterator(); i.hasNext();) 1271 { 1272 MBeanMetaData metadata = (MBeanMetaData)i.next(); 1273 ObjectName name = metadata.getObjectName(); 1274 Hashtable props = name.getKeyPropertyList(); 1275 1276 String domain = name.getDomain(); 1277 if (Utils.wildcardMatch(patternDomain, domain)) 1278 { 1279 if (pattern.isPropertyPattern()) 1281 { 1282 if (patternProps.size() == 0) 1284 { 1285 set.add(name); 1287 } 1288 else 1289 { 1290 boolean found = true; 1293 for (Iterator j = patternProps.entrySet().iterator(); j.hasNext();) 1294 { 1295 Map.Entry entry = (Map.Entry )j.next(); 1296 Object patternKey = entry.getKey(); 1297 Object patternValue = entry.getValue(); 1298 if (patternKey.equals("*")) 1299 { 1300 continue; 1301 } 1302 1303 if (!props.containsKey(patternKey)) 1305 { 1306 found = false; 1308 break; 1309 } 1310 else 1311 { 1312 Object value = props.get(patternKey); 1314 if (value == null && patternValue == null) 1315 { 1316 continue; 1318 } 1319 if (value != null && value.equals(patternValue)) 1320 { 1321 continue; 1323 } 1324 found = false; 1326 break; 1327 } 1328 } 1329 if (found) set.add(name); 1330 } 1331 } 1332 else 1333 { 1334 if (props.entrySet().equals(patternProps.entrySet())) set.add(name); 1335 } 1336 } 1337 } 1338 return set; 1339 } 1340 1341 1345 private Set filterMBeansBySecurity(Set mbeans, boolean instances) 1346 { 1347 SecurityManager sm = System.getSecurityManager(); 1348 if (sm == null) return mbeans; 1349 1350 HashSet set = new HashSet (); 1351 for (Iterator i = mbeans.iterator(); i.hasNext();) 1352 { 1353 ObjectName name = (ObjectName )i.next(); 1354 try 1355 { 1356 MBeanMetaData metadata = findMBeanMetaData(name); 1357 String className = metadata.getMBeanInfo().getClassName(); 1358 sm.checkPermission(new MBeanPermission (className, "-", name, instances ? "queryMBeans" : "queryNames")); 1359 set.add(name); 1360 } 1361 catch (InstanceNotFoundException ignored) 1362 { 1363 continue; 1365 } 1366 catch (SecurityException ignored) 1367 { 1368 } 1370 } 1371 return set; 1372 } 1373 1374 1378 private Set filterMBeansByQuery(Set scope, QueryExp filter) 1379 { 1380 if (filter == null) return scope; 1381 1382 Set set = new HashSet (); 1383 for (Iterator i = scope.iterator(); i.hasNext();) 1384 { 1385 ObjectName name = (ObjectName )i.next(); 1386 filter.setMBeanServer(this); 1387 try 1388 { 1389 if (filter.apply(name)) set.add(name); 1390 } 1391 catch (BadStringOperationException ignored) 1392 { 1393 } 1394 catch (BadBinaryOpValueExpException ignored) 1395 { 1396 } 1397 catch (BadAttributeValueExpException x) 1398 { 1399 } 1400 catch (InvalidApplicationException x) 1401 { 1402 } 1403 catch (SecurityException x) 1404 { 1405 } 1406 catch (Exception x) 1407 { 1408 } 1410 } 1411 return set; 1412 } 1413 1414 1420 private ObjectName normalizeObjectName(ObjectName name) 1421 { 1422 if (name == null) return null; 1423 1424 String defaultDomain = getDefaultDomain(); 1425 String domain = name.getDomain(); 1426 1427 if (domain.length() == 0 && defaultDomain.length() > 0) 1428 { 1429 StringBuffer buffer = new StringBuffer (defaultDomain).append(":").append(name.getKeyPropertyListString()); 1433 if (name.isPropertyPattern()) 1434 { 1435 if (name.getKeyPropertyList().size() > 0) 1436 buffer.append(",*"); 1437 else 1438 buffer.append("*"); 1439 } 1440 try 1441 { 1442 name = new ObjectName (buffer.toString()); 1443 } 1444 catch (MalformedObjectNameException ignored) 1445 { 1446 } 1447 } 1448 return name; 1449 } 1450 1451 1455 private ObjectName secureObjectName(ObjectName name) 1456 { 1457 if (name == null) return null; 1462 return ObjectName.getInstance(name); 1463 } 1464} 1465 | Popular Tags |