1 /* 2 * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.IOException; 25 import java.io.ObjectInputStream; 26 import java.io.Serializable; 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 import java.lang.management.ManagementFactory; 30 import java.lang.ref.WeakReference; 31 import java.lang.reflect.AccessibleObject; 32 import java.lang.reflect.Constructor; 33 import java.lang.reflect.InvocationTargetException; 34 import java.lang.reflect.Method; 35 import java.lang.reflect.Modifier; 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.HashMap; 39 import java.util.HashSet; 40 import java.util.Iterator; 41 import java.util.List; 42 import java.util.Map; 43 import java.util.Set; 44 import java.util.WeakHashMap; 45 import java.util.concurrent.Callable; 46 import java.util.concurrent.ConcurrentHashMap; 47 import java.util.concurrent.ConcurrentMap; 48 import javax.management.Attribute; 49 import javax.management.AttributeList; 50 import javax.management.AttributeNotFoundException; 51 import javax.management.DynamicMBean; 52 import javax.management.InstanceAlreadyExistsException; 53 import javax.management.InstanceNotFoundException; 54 import javax.management.IntrospectionException; 55 import javax.management.InvalidAttributeValueException; 56 import javax.management.ListenerNotFoundException; 57 import javax.management.MBeanAttributeInfo; 58 import javax.management.MBeanConstructorInfo; 59 import javax.management.MBeanException; 60 import javax.management.MBeanInfo; 61 import javax.management.MBeanNotificationInfo; 62 import javax.management.MBeanOperationInfo; 63 import javax.management.MBeanRegistration; 64 import javax.management.MBeanRegistrationException; 65 import javax.management.MBeanServer; 66 import javax.management.MBeanServerBuilder; 67 import javax.management.MBeanServerConnection; 68 import javax.management.MBeanServerDelegate; 69 import javax.management.MBeanServerFactory; 70 import javax.management.MBeanServerNotification; 71 import javax.management.MalformedObjectNameException; 72 import javax.management.NotCompliantMBeanException; 73 import javax.management.Notification; 74 import javax.management.NotificationBroadcaster; 75 import javax.management.NotificationBroadcasterSupport; 76 import javax.management.NotificationEmitter; 77 import javax.management.NotificationFilter; 78 import javax.management.NotificationListener; 79 import javax.management.ObjectInstance; 80 import javax.management.ObjectName; 81 import javax.management.OperationsException; 82 import javax.management.QueryEval; 83 import javax.management.QueryExp; 84 import javax.management.ReflectionException; 85 import javax.management.RuntimeErrorException; 86 import javax.management.RuntimeMBeanException; 87 import javax.management.StandardMBean; 88 import javax.management.loading.ClassLoaderRepository; 89 import javax.management.remote.JMXConnector; 90 import javax.management.remote.JMXConnectorFactory; 91 import javax.management.remote.JMXConnectorServer; 92 import javax.management.remote.JMXConnectorServerFactory; 93 import javax.management.remote.JMXServiceURL; 94 95 import jdk.test.lib.Utils; 96 97 /* 98 * @test OldMBeanServerTest.java 99 * @bug 5072268 100 * @summary Test that nothing assumes a post-1.2 MBeanServer 101 * @author Eamonn McManus 102 * @library /test/lib 103 * @modules java.management.rmi 104 * @run main/othervm -ea OldMBeanServerTest 105 */ 106 107 /* 108 * We defined the MBeanServerBuilder class and the associated system 109 * property javax.management.builder.initial in version 1.2 of the JMX 110 * spec. That amounts to a guarantee that someone can set the property 111 * to an MBeanServer that only knows about JMX 1.2 semantics, and if they 112 * only do JMX 1.2 operations, everything should work. This test is a 113 * sanity check that ensures we don't inadvertently make any API changes 114 * that stop that from being true. It includes a complete (if slow) 115 * MBeanServer implementation. That implementation doesn't replicate the 116 * mandated exception behaviour everywhere, though, since there's lots of 117 * arbitrary cruft in that. Also, the behaviour of concurrent unregisterMBean 118 * calls is incorrect in detail. 119 */ 120 121 public class OldMBeanServerTest { 122 private static MBeanServerConnection mbsc; 123 private static String failure; 124 main(String[] args)125 public static void main(String[] args) throws Exception { 126 if (!OldMBeanServerTest.class.desiredAssertionStatus()) 127 throw new Exception("Test must be run with -ea"); 128 129 System.setProperty("javax.management.builder.initial", 130 OldMBeanServerBuilder.class.getName()); 131 assert MBeanServerFactory.newMBeanServer() instanceof OldMBeanServer; 132 133 System.out.println("=== RUNNING TESTS WITH LOCAL MBEANSERVER ==="); 134 runTests(new Callable<MBeanServerConnection>() { 135 public MBeanServerConnection call() { 136 return MBeanServerFactory.newMBeanServer(); 137 } 138 }, null); 139 140 System.out.println("=== RUNNING TESTS THROUGH CONNECTOR ==="); 141 ConnectionBuilder builder = new ConnectionBuilder(); 142 runTests(builder, builder); 143 144 if (failure == null) 145 System.out.println("TEST PASSED"); 146 else 147 throw new Exception("TEST FAILED: " + failure); 148 } 149 150 private static class ConnectionBuilder 151 implements Callable<MBeanServerConnection>, Runnable { 152 private JMXConnector connector; call()153 public MBeanServerConnection call() { 154 MBeanServer mbs = MBeanServerFactory.newMBeanServer(); 155 try { 156 JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); 157 JMXConnectorServer cs = 158 JMXConnectorServerFactory.newJMXConnectorServer( 159 url, null, mbs); 160 cs.start(); 161 JMXServiceURL addr = cs.getAddress(); 162 connector = JMXConnectorFactory.connect(addr); 163 return connector.getMBeanServerConnection(); 164 } catch (IOException e) { 165 throw new RuntimeException(e); 166 } 167 } run()168 public void run() { 169 if (connector != null) { 170 try { 171 connector.close(); 172 } catch (IOException e) { 173 throw new RuntimeException(e); 174 } 175 } 176 } 177 } 178 runTests( Callable<MBeanServerConnection> maker, Runnable breaker)179 private static void runTests( 180 Callable<MBeanServerConnection> maker, Runnable breaker) 181 throws Exception { 182 for (Method m : OldMBeanServerTest.class.getDeclaredMethods()) { 183 if (Modifier.isStatic(m.getModifiers()) && 184 m.getName().startsWith("test") && 185 m.getParameterTypes().length == 0) { 186 ExpectException expexc = m.getAnnotation(ExpectException.class); 187 mbsc = maker.call(); 188 try { 189 m.invoke(null); 190 if (expexc != null) { 191 failure = 192 m.getName() + " did not got expected exception " + 193 expexc.value().getName(); 194 System.out.println(failure); 195 } else 196 System.out.println(m.getName() + " OK"); 197 } catch (InvocationTargetException ite) { 198 Throwable t = ite.getCause(); 199 String prob = null; 200 if (expexc != null) { 201 if (expexc.value().isInstance(t)) { 202 System.out.println(m.getName() + " OK (got expected " + 203 expexc.value().getName() + ")"); 204 } else 205 prob = "got wrong exception"; 206 } else 207 prob = "got exception"; 208 if (prob != null) { 209 failure = m.getName() + ": " + prob + " " + 210 t.getClass().getName(); 211 System.out.println(failure); 212 t.printStackTrace(System.out); 213 } 214 } finally { 215 if (breaker != null) 216 breaker.run(); 217 } 218 } 219 } 220 } 221 222 @Retention(RetentionPolicy.RUNTIME) 223 private static @interface ExpectException { value()224 Class<? extends Exception> value(); 225 } 226 227 public static interface BoringMBean { getName()228 public String getName(); add(int x, int y)229 public int add(int x, int y); 230 } 231 232 // This class is Serializable so we can createMBean a StandardMBean 233 // that contains it. Not recommended practice in general -- 234 // should we have a StandardMBean constructor that takes a class 235 // name and constructor parameters? 236 public static class Boring implements BoringMBean, Serializable { getName()237 public String getName() { 238 return "Jessica"; 239 } 240 add(int x, int y)241 public int add(int x, int y) { 242 return x + y; 243 } 244 } 245 246 public static interface BoringNotifierMBean extends BoringMBean { send()247 public void send(); 248 } 249 250 public static class BoringNotifier 251 extends Boring implements BoringNotifierMBean, NotificationBroadcaster { 252 private final NotificationBroadcasterSupport nbs = 253 new NotificationBroadcasterSupport(); 254 addNotificationListener( NotificationListener listener, NotificationFilter filter, Object handback)255 public void addNotificationListener( 256 NotificationListener listener, NotificationFilter filter, Object handback) 257 throws IllegalArgumentException { 258 nbs.addNotificationListener(listener, filter, handback); 259 } 260 removeNotificationListener(NotificationListener listener)261 public void removeNotificationListener(NotificationListener listener) 262 throws ListenerNotFoundException { 263 nbs.removeNotificationListener(listener); 264 } 265 getNotificationInfo()266 public MBeanNotificationInfo[] getNotificationInfo() { 267 return null; 268 } 269 send()270 public void send() { 271 Notification n = new Notification("type.type", this, 0L); 272 nbs.sendNotification(n); 273 } 274 } 275 276 private static class CountListener implements NotificationListener { 277 volatile int count; handleNotification(Notification n, Object h)278 public void handleNotification(Notification n, Object h) { 279 if (h == null) 280 h = 1; 281 count += (Integer) h; 282 } waitForCount(int expect)283 void waitForCount(int expect) throws InterruptedException { 284 long deadline = System.currentTimeMillis() + Utils.adjustTimeout(2000); 285 while (count < expect && System.currentTimeMillis() < deadline) 286 Thread.sleep(1); 287 assert count == expect; 288 } 289 } 290 testBasic()291 private static void testBasic() throws Exception { 292 CountListener countListener = new CountListener(); 293 mbsc.addNotificationListener( 294 MBeanServerDelegate.DELEGATE_NAME, countListener, null, null); 295 assert countListener.count == 0; 296 ObjectName name = new ObjectName("a:b=c"); 297 if (mbsc instanceof MBeanServer) 298 ((MBeanServer) mbsc).registerMBean(new Boring(), name); 299 else 300 mbsc.createMBean(Boring.class.getName(), name); 301 countListener.waitForCount(1); 302 assert mbsc.isRegistered(name); 303 assert mbsc.queryNames(null, null).contains(name); 304 assert mbsc.getAttribute(name, "Name").equals("Jessica"); 305 assert mbsc.invoke( 306 name, "add", new Object[] {2, 3}, new String[] {"int", "int"}) 307 .equals(5); 308 mbsc.unregisterMBean(name); 309 countListener.waitForCount(2); 310 assert !mbsc.isRegistered(name); 311 assert !mbsc.queryNames(null, null).contains(name); 312 313 mbsc.createMBean(BoringNotifier.class.getName(), name); 314 countListener.waitForCount(3); 315 CountListener boringListener = new CountListener(); 316 class AlwaysNotificationFilter implements NotificationFilter { 317 public boolean isNotificationEnabled(Notification notification) { 318 return true; 319 } 320 } 321 mbsc.addNotificationListener( 322 name, boringListener, new AlwaysNotificationFilter(), 5); 323 mbsc.invoke(name, "send", null, null); 324 boringListener.waitForCount(5); 325 } 326 testPrintAttrs()327 private static void testPrintAttrs() throws Exception { 328 printAttrs(mbsc, null); 329 } 330 testPlatformMBeanServer()331 private static void testPlatformMBeanServer() throws Exception { 332 MBeanServer pmbs = ManagementFactory.getPlatformMBeanServer(); 333 assert pmbs instanceof OldMBeanServer; 334 // Preceding assertion could be violated if at some stage we wrap 335 // the Platform MBeanServer. In that case we can still check that 336 // it is ultimately an OldMBeanServer for example by adding a 337 // counter to getAttribute and checking that it is incremented 338 // when we call pmbs.getAttribute. 339 340 printAttrs(pmbs, UnsupportedOperationException.class); 341 ObjectName memoryMXBeanName = 342 new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME); 343 pmbs.invoke(memoryMXBeanName, "gc", null, null); 344 } 345 printAttrs( MBeanServerConnection mbsc1, Class<? extends Exception> expectX)346 private static void printAttrs( 347 MBeanServerConnection mbsc1, Class<? extends Exception> expectX) 348 throws Exception { 349 Set<ObjectName> names = mbsc1.queryNames(null, null); 350 for (ObjectName name : names) { 351 System.out.println(name + ":"); 352 MBeanInfo mbi = mbsc1.getMBeanInfo(name); 353 MBeanAttributeInfo[] mbais = mbi.getAttributes(); 354 for (MBeanAttributeInfo mbai : mbais) { 355 String attr = mbai.getName(); 356 Object value; 357 try { 358 value = mbsc1.getAttribute(name, attr); 359 } catch (Exception e) { 360 if (expectX != null && expectX.isInstance(e)) 361 value = "<" + e + ">"; 362 else 363 throw e; 364 } 365 String s = " " + attr + " = " + value; 366 if (s.length() > 80) 367 s = s.substring(0, 77) + "..."; 368 System.out.println(s); 369 } 370 } 371 } 372 testJavaxManagementStandardMBean()373 private static void testJavaxManagementStandardMBean() throws Exception { 374 ObjectName name = new ObjectName("a:b=c"); 375 Object mbean = new StandardMBean(new Boring(), BoringMBean.class); 376 mbsc.createMBean( 377 StandardMBean.class.getName(), name, 378 new Object[] {new Boring(), BoringMBean.class}, 379 new String[] {Object.class.getName(), Class.class.getName()}); 380 assert mbsc.getAttribute(name, "Name").equals("Jessica"); 381 assert mbsc.invoke( 382 name, "add", new Object[] {2, 3}, new String[] {"int", "int"}) 383 .equals(5); 384 mbsc.unregisterMBean(name); 385 } 386 testConnector()387 private static void testConnector() throws Exception { 388 } 389 390 public static class OldMBeanServerBuilder extends MBeanServerBuilder { newMBeanServer( String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate)391 public MBeanServer newMBeanServer( 392 String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate) { 393 return new OldMBeanServer(defaultDomain, delegate); 394 } 395 } 396 397 public static class OldMBeanServer implements MBeanServer { 398 // We pretend there's a ClassLoader MBean representing the Class Loader 399 // Repository and intercept references to it where necessary to keep up 400 // the pretence. This allows us to fake the right behaviour for 401 // the omitted-ClassLoader versions of createMBean and instantiate 402 // (which are not the same as passing a null for the ClassLoader parameter 403 // of the versions that have one). 404 private static final ObjectName clrName; 405 static { 406 try { 407 clrName = 408 new ObjectName("JMImplementation:type=ClassLoaderRepository"); 409 } catch (MalformedObjectNameException e) { 410 throw new RuntimeException(e); 411 } 412 } 413 414 private final ConcurrentMap<ObjectName, DynamicMBean> mbeans = 415 new ConcurrentHashMap<ObjectName, DynamicMBean>(); 416 private final ConcurrentMap<ObjectName, ListenerTable> listenerMap = 417 new ConcurrentHashMap<ObjectName, ListenerTable>(); 418 private final String defaultDomain; 419 private final MBeanServerDelegate delegate; 420 private final ClassLoaderRepositoryImpl clr = 421 new ClassLoaderRepositoryImpl(); 422 OldMBeanServer(String defaultDomain, MBeanServerDelegate delegate)423 OldMBeanServer(String defaultDomain, MBeanServerDelegate delegate) { 424 this.defaultDomain = defaultDomain; 425 this.delegate = delegate; 426 try { 427 registerMBean(delegate, MBeanServerDelegate.DELEGATE_NAME); 428 } catch (Exception e) { 429 throw new RuntimeException(e); 430 } 431 } 432 createMBean(String className, ObjectName name)433 public ObjectInstance createMBean(String className, ObjectName name) 434 throws ReflectionException, InstanceAlreadyExistsException, 435 MBeanRegistrationException, MBeanException, 436 NotCompliantMBeanException { 437 return createMBean(className, name, null, null); 438 } 439 createMBean( String className, ObjectName name, ObjectName loaderName)440 public ObjectInstance createMBean( 441 String className, ObjectName name, ObjectName loaderName) 442 throws ReflectionException, InstanceAlreadyExistsException, 443 MBeanRegistrationException, MBeanException, 444 NotCompliantMBeanException, InstanceNotFoundException { 445 return createMBean(className, name, loaderName, null, null); 446 } 447 createMBean( String className, ObjectName name, Object[] params, String[] signature)448 public ObjectInstance createMBean( 449 String className, ObjectName name, Object[] params, String[] signature) 450 throws ReflectionException, InstanceAlreadyExistsException, 451 MBeanRegistrationException, MBeanException, 452 NotCompliantMBeanException { 453 try { 454 return createMBean(className, name, clrName, params, signature); 455 } catch (InstanceNotFoundException ex) { 456 throw new RuntimeException(ex); // can't happen 457 } 458 } 459 createMBean( String className, ObjectName name, ObjectName loaderName, Object[] params, String[] signature)460 public ObjectInstance createMBean( 461 String className, ObjectName name, ObjectName loaderName, 462 Object[] params, String[] signature) 463 throws ReflectionException, InstanceAlreadyExistsException, 464 MBeanRegistrationException, MBeanException, 465 NotCompliantMBeanException, InstanceNotFoundException { 466 Object mbean = instantiate(className, loaderName, params, signature); 467 return registerMBean(mbean, name); 468 } 469 forbidJMImpl(ObjectName name)470 private void forbidJMImpl(ObjectName name) { 471 if (name.getDomain().equals("JMImplementation") && 472 mbeans.containsKey(MBeanServerDelegate.DELEGATE_NAME)) 473 throw new IllegalArgumentException("JMImplementation reserved"); 474 } 475 registerMBean(Object object, ObjectName name)476 public ObjectInstance registerMBean(Object object, ObjectName name) 477 throws InstanceAlreadyExistsException, MBeanRegistrationException, 478 NotCompliantMBeanException { 479 forbidJMImpl(name); 480 if (name.isPattern()) 481 throw new IllegalArgumentException(name.toString()); 482 // This is the only place we check for wildcards. Since you 483 // can't register a wildcard name, other operations that supply 484 // one will get InstanceNotFoundException when they look it up. 485 486 DynamicMBean mbean; 487 if (object instanceof DynamicMBean) 488 mbean = (DynamicMBean) object; 489 else 490 mbean = standardToDynamic(object); 491 MBeanRegistration reg = mbeanRegistration(object); 492 try { 493 name = reg.preRegister(this, name); 494 } catch (Exception e) { 495 throw new MBeanRegistrationException(e); 496 } 497 DynamicMBean put = mbeans.putIfAbsent(name, mbean); 498 if (put != null) { 499 reg.postRegister(false); 500 throw new InstanceAlreadyExistsException(name.toString()); 501 } 502 reg.postRegister(true); 503 504 if (object instanceof ClassLoader) 505 clr.addLoader((ClassLoader) object); 506 507 Notification n = new MBeanServerNotification( 508 MBeanServerNotification.REGISTRATION_NOTIFICATION, 509 MBeanServerDelegate.DELEGATE_NAME, 510 0, 511 name); 512 delegate.sendNotification(n); 513 514 String className = mbean.getMBeanInfo().getClassName(); 515 return new ObjectInstance(name, className); 516 } 517 unregisterMBean(ObjectName name)518 public void unregisterMBean(ObjectName name) 519 throws InstanceNotFoundException, MBeanRegistrationException { 520 521 forbidJMImpl(name); 522 523 DynamicMBean mbean = getMBean(name); 524 if (mbean == null) 525 throw new InstanceNotFoundException(name.toString()); 526 527 MBeanRegistration reg = mbeanRegistration(mbean); 528 try { 529 reg.preDeregister(); 530 } catch (Exception e) { 531 throw new MBeanRegistrationException(e); 532 } 533 if (!mbeans.remove(name, mbean)) 534 throw new InstanceNotFoundException(name.toString()); 535 // This is incorrect because we've invoked preDeregister 536 537 Object userMBean = getUserMBean(mbean); 538 if (userMBean instanceof ClassLoader) 539 clr.removeLoader((ClassLoader) userMBean); 540 541 Notification n = new MBeanServerNotification( 542 MBeanServerNotification.REGISTRATION_NOTIFICATION, 543 MBeanServerDelegate.DELEGATE_NAME, 544 0, 545 name); 546 delegate.sendNotification(n); 547 548 reg.postDeregister(); 549 } 550 getObjectInstance(ObjectName name)551 public ObjectInstance getObjectInstance(ObjectName name) 552 throws InstanceNotFoundException { 553 DynamicMBean mbean = getMBean(name); 554 return new ObjectInstance(name, mbean.getMBeanInfo().getClassName()); 555 } 556 557 private static class TrueQueryExp implements QueryExp { apply(ObjectName name)558 public boolean apply(ObjectName name) { 559 return true; 560 } 561 setMBeanServer(MBeanServer s)562 public void setMBeanServer(MBeanServer s) {} 563 } 564 private static final QueryExp trueQuery = new TrueQueryExp(); 565 queryMBeans(ObjectName name, QueryExp query)566 public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { 567 Set<ObjectInstance> instances = newSet(); 568 if (name == null) 569 name = ObjectName.WILDCARD; 570 if (query == null) 571 query = trueQuery; 572 MBeanServer oldMBS = QueryEval.getMBeanServer(); 573 try { 574 query.setMBeanServer(this); 575 for (ObjectName n : mbeans.keySet()) { 576 if (name.apply(n)) { 577 try { 578 if (query.apply(n)) 579 instances.add(getObjectInstance(n)); 580 } catch (Exception e) { 581 // OK: Ignore this MBean in the result 582 } 583 } 584 } 585 } finally { 586 query.setMBeanServer(oldMBS); 587 } 588 return instances; 589 } 590 queryNames(ObjectName name, QueryExp query)591 public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { 592 Set<ObjectInstance> instances = queryMBeans(name, query); 593 Set<ObjectName> names = newSet(); 594 for (ObjectInstance instance : instances) 595 names.add(instance.getObjectName()); 596 return names; 597 } 598 isRegistered(ObjectName name)599 public boolean isRegistered(ObjectName name) { 600 return mbeans.containsKey(name); 601 } 602 getMBeanCount()603 public Integer getMBeanCount() { 604 return mbeans.size(); 605 } 606 getAttribute(ObjectName name, String attribute)607 public Object getAttribute(ObjectName name, String attribute) 608 throws MBeanException, AttributeNotFoundException, 609 InstanceNotFoundException, ReflectionException { 610 return getMBean(name).getAttribute(attribute); 611 } 612 getAttributes(ObjectName name, String[] attributes)613 public AttributeList getAttributes(ObjectName name, String[] attributes) 614 throws InstanceNotFoundException, ReflectionException { 615 return getMBean(name).getAttributes(attributes); 616 } 617 setAttribute(ObjectName name, Attribute attribute)618 public void setAttribute(ObjectName name, Attribute attribute) 619 throws InstanceNotFoundException, AttributeNotFoundException, 620 InvalidAttributeValueException, MBeanException, 621 ReflectionException { 622 getMBean(name).setAttribute(attribute); 623 } 624 setAttributes( ObjectName name, AttributeList attributes)625 public AttributeList setAttributes( 626 ObjectName name, AttributeList attributes) 627 throws InstanceNotFoundException, ReflectionException { 628 return getMBean(name).setAttributes(attributes); 629 } 630 invoke( ObjectName name, String operationName, Object[] params, String[] signature)631 public Object invoke( 632 ObjectName name, String operationName, Object[] params, 633 String[] signature) 634 throws InstanceNotFoundException, MBeanException, ReflectionException { 635 return getMBean(name).invoke(operationName, params, signature); 636 } 637 getDefaultDomain()638 public String getDefaultDomain() { 639 return defaultDomain; 640 } 641 getDomains()642 public String[] getDomains() { 643 Set<String> domains = newSet(); 644 for (ObjectName name : mbeans.keySet()) 645 domains.add(name.getDomain()); 646 return domains.toArray(new String[0]); 647 } 648 649 // ClassCastException if MBean is not a NotificationBroadcaster addNotificationListener( ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback)650 public void addNotificationListener( 651 ObjectName name, NotificationListener listener, 652 NotificationFilter filter, Object handback) 653 throws InstanceNotFoundException { 654 NotificationBroadcaster userMBean = 655 (NotificationBroadcaster) getUserMBean(name); 656 NotificationListener wrappedListener = 657 wrappedListener(name, userMBean, listener); 658 userMBean.addNotificationListener(wrappedListener, filter, handback); 659 } 660 addNotificationListener( ObjectName name, ObjectName listener, NotificationFilter filter, Object handback)661 public void addNotificationListener( 662 ObjectName name, ObjectName listener, 663 NotificationFilter filter, Object handback) 664 throws InstanceNotFoundException { 665 NotificationListener nl = 666 (NotificationListener) getUserMBean(listener); 667 addNotificationListener(name, nl, filter, handback); 668 } 669 removeNotificationListener( ObjectName name, ObjectName listener)670 public void removeNotificationListener( 671 ObjectName name, ObjectName listener) 672 throws InstanceNotFoundException, ListenerNotFoundException { 673 NotificationListener nl = 674 (NotificationListener) getUserMBean(listener); 675 removeNotificationListener(name, nl); 676 } 677 removeNotificationListener( ObjectName name, ObjectName listener, NotificationFilter filter, Object handback)678 public void removeNotificationListener( 679 ObjectName name, ObjectName listener, 680 NotificationFilter filter, Object handback) 681 throws InstanceNotFoundException, ListenerNotFoundException { 682 NotificationListener nl = 683 (NotificationListener) getUserMBean(listener); 684 removeNotificationListener(name, nl, filter, handback); 685 } 686 removeNotificationListener( ObjectName name, NotificationListener listener)687 public void removeNotificationListener( 688 ObjectName name, NotificationListener listener) 689 throws InstanceNotFoundException, ListenerNotFoundException { 690 NotificationBroadcaster userMBean = 691 (NotificationBroadcaster) getUserMBean(name); 692 NotificationListener wrappedListener = 693 wrappedListener(name, userMBean, listener); 694 userMBean.removeNotificationListener(wrappedListener); 695 } 696 removeNotificationListener( ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback)697 public void removeNotificationListener( 698 ObjectName name, NotificationListener listener, 699 NotificationFilter filter, Object handback) 700 throws InstanceNotFoundException, ListenerNotFoundException { 701 NotificationEmitter userMBean = 702 (NotificationEmitter) getMBean(name); 703 NotificationListener wrappedListener = 704 wrappedListener(name, userMBean, listener); 705 userMBean.removeNotificationListener(wrappedListener, filter, handback); 706 } 707 getMBeanInfo(ObjectName name)708 public MBeanInfo getMBeanInfo(ObjectName name) 709 throws InstanceNotFoundException, IntrospectionException, 710 ReflectionException { 711 return getMBean(name).getMBeanInfo(); 712 } 713 isInstanceOf(ObjectName name, String className)714 public boolean isInstanceOf(ObjectName name, String className) 715 throws InstanceNotFoundException { 716 DynamicMBean mbean = getMBean(name); 717 String mbeanClassName = mbean.getMBeanInfo().getClassName(); 718 if (className.equals(mbeanClassName)) 719 return true; 720 ClassLoader loader = getUserMBean(mbean).getClass().getClassLoader(); 721 try { 722 Class<?> mbeanClass = Class.forName(mbeanClassName, false, loader); 723 Class<?> isInstClass = Class.forName(className, false, loader); 724 return isInstClass.isAssignableFrom(mbeanClass); 725 } catch (ClassNotFoundException e) { 726 return false; 727 } 728 } 729 instantiate(String className)730 public Object instantiate(String className) 731 throws ReflectionException, MBeanException { 732 return instantiate(className, null, null); 733 } 734 instantiate(String className, ObjectName loaderName)735 public Object instantiate(String className, ObjectName loaderName) 736 throws ReflectionException, MBeanException, InstanceNotFoundException { 737 return instantiate(className, loaderName, null, null); 738 } 739 instantiate( String className, Object[] params, String[] signature)740 public Object instantiate( 741 String className, Object[] params, String[] signature) 742 throws ReflectionException, MBeanException { 743 try { 744 return instantiate(className, clrName, params, signature); 745 } catch (InstanceNotFoundException e) { 746 throw new RuntimeException(e); // can't happen 747 } 748 } 749 instantiate( String className, ObjectName loaderName, Object[] params, String[] signature)750 public Object instantiate( 751 String className, ObjectName loaderName, 752 Object[] params, String[] signature) 753 throws ReflectionException, MBeanException, InstanceNotFoundException { 754 755 if (params == null) 756 params = new Object[0]; 757 if (signature == null) 758 signature = new String[0]; 759 760 ClassLoader loader; 761 if (loaderName == null) 762 loader = this.getClass().getClassLoader(); 763 else if (loaderName.equals(clrName)) 764 loader = clr; 765 else 766 loader = (ClassLoader) getMBean(loaderName); 767 768 Class<?> c; 769 try { 770 c = Class.forName(className, false, loader); 771 } catch (ClassNotFoundException e) { 772 throw new ReflectionException(e); 773 } 774 775 Constructor[] constrs = c.getConstructors(); 776 Constructor found = null; 777 findconstr: 778 for (Constructor constr : constrs) { 779 Class<?>[] cTypes = constr.getParameterTypes(); 780 if (cTypes.length == signature.length) { 781 for (int i = 0; i < cTypes.length; i++) { 782 if (!cTypes[i].getName().equals(signature[i])) 783 continue findconstr; 784 } 785 found = constr; 786 break findconstr; 787 } 788 } 789 if (found == null) { 790 Exception x = new NoSuchMethodException( 791 className + Arrays.toString(signature)); 792 throw new ReflectionException(x); 793 } 794 return invokeSomething(found, null, params); 795 } 796 797 @Deprecated deserialize(ObjectName name, byte[] data)798 public ObjectInputStream deserialize(ObjectName name, byte[] data) 799 throws InstanceNotFoundException, OperationsException { 800 throw new UnsupportedOperationException(); 801 } 802 803 @Deprecated deserialize(String className, byte[] data)804 public ObjectInputStream deserialize(String className, byte[] data) 805 throws OperationsException, ReflectionException { 806 throw new UnsupportedOperationException(); 807 } 808 809 @Deprecated deserialize( String className, ObjectName loaderName, byte[] data)810 public ObjectInputStream deserialize( 811 String className, ObjectName loaderName, byte[] data) 812 throws InstanceNotFoundException, OperationsException, ReflectionException { 813 throw new UnsupportedOperationException(); 814 } 815 getClassLoaderFor(ObjectName mbeanName)816 public ClassLoader getClassLoaderFor(ObjectName mbeanName) 817 throws InstanceNotFoundException { 818 DynamicMBean mbean = getMBean(mbeanName); 819 Object userMBean = getUserMBean(mbean); 820 return userMBean.getClass().getClassLoader(); 821 } 822 getClassLoader(ObjectName loaderName)823 public ClassLoader getClassLoader(ObjectName loaderName) 824 throws InstanceNotFoundException { 825 return (ClassLoader) getMBean(loaderName); 826 } 827 getClassLoaderRepository()828 public ClassLoaderRepository getClassLoaderRepository() { 829 return new ClassLoaderRepository() { 830 public Class<?> loadClass(String className) 831 throws ClassNotFoundException { 832 return clr.loadClass(className); 833 } 834 835 public Class<?> loadClassWithout( 836 ClassLoader exclude, String className) 837 throws ClassNotFoundException { 838 return clr.loadClassWithout(exclude, className); 839 } 840 841 public Class<?> loadClassBefore( 842 ClassLoader stop, String className) 843 throws ClassNotFoundException { 844 return clr.loadClassBefore(stop, className); 845 } 846 }; 847 } 848 849 private static class ClassLoaderRepositoryImpl 850 extends ClassLoader implements ClassLoaderRepository { 851 private List<ClassLoader> loaders = newList(); 852 { 853 loaders.add(this.getClass().getClassLoader()); 854 // We also behave as if the system class loader were in 855 // the repository, since we do nothing to stop delegation 856 // to the parent, which is the system class loader, and 857 // that delegation happens before our findClass is called. 858 } 859 addLoader(ClassLoader loader)860 void addLoader(ClassLoader loader) { 861 loaders.add(loader); 862 } 863 removeLoader(ClassLoader loader)864 void removeLoader(ClassLoader loader) { 865 if (!loaders.remove(loader)) 866 throw new RuntimeException("Loader was not in CLR!"); 867 } 868 loadClassWithout( ClassLoader exclude, String className)869 public Class<?> loadClassWithout( 870 ClassLoader exclude, String className) 871 throws ClassNotFoundException { 872 return loadClassWithoutBefore(exclude, null, className); 873 } 874 loadClassBefore(ClassLoader stop, String className)875 public Class<?> loadClassBefore(ClassLoader stop, String className) 876 throws ClassNotFoundException { 877 return loadClassWithoutBefore(null, stop, className); 878 } 879 loadClassWithoutBefore( ClassLoader exclude, ClassLoader stop, String className)880 private Class<?> loadClassWithoutBefore( 881 ClassLoader exclude, ClassLoader stop, String className) 882 throws ClassNotFoundException { 883 for (ClassLoader loader : loaders) { 884 if (loader == exclude) 885 continue; 886 if (loader == stop) 887 break; 888 try { 889 return Class.forName(className, false, loader); 890 } catch (ClassNotFoundException e) { 891 // OK: try others 892 } 893 } 894 throw new ClassNotFoundException(className); 895 } 896 897 @Override findClass(String className)898 protected Class<?> findClass(String className) 899 throws ClassNotFoundException { 900 return loadClassWithout(null, className); 901 } 902 } 903 904 /* There is zero or one ListenerTable per MBean. 905 * The ListenerTable stuff is complicated. We want to rewrite the 906 * source of notifications so that if the source of a notification 907 * from the MBean X is a reference to X itself, it gets replaced 908 * by X's ObjectName. To do this, we wrap the user's listener in 909 * a RewriteListener. But if the same listener is added a second 910 * time (perhaps with a different filter or handback) we must 911 * reuse the same RewriteListener so that the two-argument 912 * removeNotificationListener(ObjectName,NotificationListener) will 913 * correctly remove both listeners. This means we must remember the 914 * mapping from listener to WrappedListener. But if the MBean 915 * discards its listeners (as a result of removeNL or spontaneously) 916 * then we don't want to keep a reference to the WrappedListener. 917 * So we have tons of WeakReferences. The key in the ListenerTable 918 * is an IdentityListener, which wraps the user's listener to ensure 919 * that identity and not equality is used during the lookup, even if 920 * the user's listener has an equals method. The value in the 921 * ListenerTable is a WeakReference wrapping a RewriteListener wrapping 922 * the same IdentityListener. Since the RewriteListener is what is 923 * added to the user's MBean, the WeakReference won't disappear as long 924 * as the MBean still has this listener. And since it references the 925 * IdentityListener, that won't disappear either. But once the 926 * RewriteListener is no longer referenced by the user's MBean, 927 * there's nothing to stop its WeakReference from being cleared, 928 * and then corresponding IdentityListener that is now only weakly 929 * referenced from the key in the table. 930 */ 931 private static class ListenerTable 932 extends WeakHashMap<NotificationListener, 933 WeakReference<NotificationListener>> { 934 } 935 936 private static class IdentityListener implements NotificationListener { 937 private final NotificationListener userListener; 938 IdentityListener(NotificationListener userListener)939 IdentityListener(NotificationListener userListener) { 940 this.userListener = userListener; 941 } 942 handleNotification( Notification notification, Object handback)943 public void handleNotification( 944 Notification notification, Object handback) { 945 userListener.handleNotification(notification, handback); 946 } 947 948 @Override equals(Object o)949 public boolean equals(Object o) { 950 return (this == o); 951 } 952 953 @Override hashCode()954 public int hashCode() { 955 return System.identityHashCode(this); 956 } 957 } 958 959 private static class RewriteListener implements NotificationListener { 960 private final ObjectName name; 961 private final Object userMBean; 962 private final NotificationListener userListener; 963 RewriteListener( ObjectName name, Object userMBean, NotificationListener userListener)964 RewriteListener( 965 ObjectName name, Object userMBean, 966 NotificationListener userListener) { 967 this.name = name; 968 this.userMBean = userMBean; 969 this.userListener = userListener; 970 } 971 handleNotification( Notification notification, Object handback)972 public void handleNotification( 973 Notification notification, Object handback) { 974 if (notification.getSource() == userMBean) 975 notification.setSource(name); 976 userListener.handleNotification(notification, handback); 977 } 978 } 979 wrappedListener( ObjectName name, Object userMBean, NotificationListener userListener)980 private NotificationListener wrappedListener( 981 ObjectName name, Object userMBean, NotificationListener userListener) 982 throws InstanceNotFoundException { 983 ListenerTable table = new ListenerTable(); 984 ListenerTable oldTable = listenerMap.putIfAbsent(name, table); 985 if (oldTable != null) 986 table = oldTable; 987 NotificationListener identityListener = 988 new IdentityListener(userListener); 989 synchronized (table) { 990 NotificationListener rewriteListener = null; 991 WeakReference<NotificationListener> wr = 992 table.get(identityListener); 993 if (wr != null) 994 rewriteListener = wr.get(); 995 if (rewriteListener == null) { 996 rewriteListener = new RewriteListener( 997 name, userMBean, identityListener); 998 wr = new WeakReference<NotificationListener>(rewriteListener); 999 table.put(identityListener, wr); 1000 } 1001 return rewriteListener; 1002 } 1003 } 1004 getMBean(ObjectName name)1005 private DynamicMBean getMBean(ObjectName name) 1006 throws InstanceNotFoundException { 1007 DynamicMBean mbean = mbeans.get(name); 1008 if (mbean == null) 1009 throw new InstanceNotFoundException(name.toString()); 1010 return mbean; 1011 } 1012 1013 private static interface WrapDynamicMBean extends DynamicMBean { getWrappedMBean()1014 public Object getWrappedMBean(); 1015 } 1016 1017 private static class StandardWrapper 1018 implements WrapDynamicMBean, MBeanRegistration { 1019 private final Map<String, AttrMethods> attrMap = newMap(); 1020 private final Map<String, List<Method>> opMap = newMap(); 1021 private static class AttrMethods { 1022 Method getter, setter; 1023 } 1024 1025 private final Object std; 1026 StandardWrapper(Object std)1027 StandardWrapper(Object std) throws NotCompliantMBeanException { 1028 this.std = std; 1029 Class<?> intf = mbeanInterface(std.getClass()); 1030 try { 1031 initMaps(intf); 1032 } catch (NotCompliantMBeanException e) { 1033 throw e; 1034 } catch (Exception e) { 1035 NotCompliantMBeanException x = 1036 new NotCompliantMBeanException(e.getMessage()); 1037 x.initCause(e); 1038 throw x; 1039 } 1040 } 1041 mbeanInterface(Class<?> c)1042 private static Class<?> mbeanInterface(Class<?> c) 1043 throws NotCompliantMBeanException { 1044 do { 1045 Class<?>[] intfs = c.getInterfaces(); 1046 String intfName = c.getName() + "MBean"; 1047 for (Class<?> intf : intfs) { 1048 if (intf.getName().equals(intfName)) 1049 return intf; 1050 } 1051 c = c.getSuperclass(); 1052 } while (c != null); 1053 throw new NotCompliantMBeanException( 1054 "Does not match Standard or Dynamic MBean patterns: " + 1055 c.getName()); 1056 } 1057 initMaps(Class<?> intf)1058 private void initMaps(Class<?> intf) throws NotCompliantMBeanException { 1059 Method[] methods = intf.getMethods(); 1060 1061 for (Method m : methods) { 1062 final String name = m.getName(); 1063 final int nParams = m.getParameterTypes().length; 1064 1065 String attrName = ""; 1066 if (name.startsWith("get")) 1067 attrName = name.substring(3); 1068 else if (name.startsWith("is") 1069 && m.getReturnType() == boolean.class) 1070 attrName = name.substring(2); 1071 1072 if (attrName.length() != 0 && m.getParameterTypes().length == 0 1073 && m.getReturnType() != void.class) { 1074 // It's a getter 1075 // Check we don't have both isX and getX 1076 AttrMethods am = attrMap.get(attrName); 1077 if (am == null) 1078 am = new AttrMethods(); 1079 else { 1080 if (am.getter != null) { 1081 final String msg = "Attribute " + attrName + 1082 " has more than one getter"; 1083 throw new NotCompliantMBeanException(msg); 1084 } 1085 } 1086 am.getter = m; 1087 attrMap.put(attrName, am); 1088 } else if (name.startsWith("set") && name.length() > 3 1089 && m.getParameterTypes().length == 1 && 1090 m.getReturnType() == void.class) { 1091 // It's a setter 1092 attrName = name.substring(3); 1093 AttrMethods am = attrMap.get(attrName); 1094 if (am == null) 1095 am = new AttrMethods(); 1096 else if (am.setter != null) { 1097 final String msg = "Attribute " + attrName + 1098 " has more than one setter"; 1099 throw new NotCompliantMBeanException(msg); 1100 } 1101 am.setter = m; 1102 attrMap.put(attrName, am); 1103 } else { 1104 // It's an operation 1105 List<Method> ops = opMap.get(name); 1106 if (ops == null) 1107 ops = newList(); 1108 ops.add(m); 1109 opMap.put(name, ops); 1110 } 1111 } 1112 /* Check that getters and setters are consistent. */ 1113 for (Map.Entry<String, AttrMethods> entry : attrMap.entrySet()) { 1114 AttrMethods am = entry.getValue(); 1115 if (am.getter != null && am.setter != null && 1116 am.getter.getReturnType() != am.setter.getParameterTypes()[0]) { 1117 final String msg = "Getter and setter for " + entry.getKey() + 1118 " have inconsistent types"; 1119 throw new NotCompliantMBeanException(msg); 1120 } 1121 } 1122 } 1123 getAttribute(String attribute)1124 public Object getAttribute(String attribute) 1125 throws AttributeNotFoundException, MBeanException, ReflectionException { 1126 AttrMethods am = attrMap.get(attribute); 1127 if (am == null || am.getter == null) 1128 throw new AttributeNotFoundException(attribute); 1129 return invokeMethod(am.getter); 1130 } 1131 setAttribute(Attribute attribute)1132 public void setAttribute(Attribute attribute) 1133 throws AttributeNotFoundException, InvalidAttributeValueException, 1134 MBeanException, ReflectionException { 1135 String name = attribute.getName(); 1136 AttrMethods am = attrMap.get(name); 1137 if (am == null || am.setter == null) 1138 throw new AttributeNotFoundException(name); 1139 invokeMethod(am.setter, attribute.getValue()); 1140 } 1141 getAttributes(String[] attributes)1142 public AttributeList getAttributes(String[] attributes) { 1143 AttributeList list = new AttributeList(); 1144 for (String attr : attributes) { 1145 try { 1146 list.add(new Attribute(attr, getAttribute(attr))); 1147 } catch (Exception e) { 1148 // OK: ignore per spec 1149 } 1150 } 1151 return list; 1152 } 1153 setAttributes(AttributeList attributes)1154 public AttributeList setAttributes(AttributeList attributes) { 1155 AttributeList list = new AttributeList(); 1156 // We carefully avoid using any new stuff from AttributeList here! 1157 for (Iterator<?> it = attributes.iterator(); it.hasNext(); ) { 1158 Attribute attr = (Attribute) it.next(); 1159 try { 1160 setAttribute(attr); 1161 list.add(attr); 1162 } catch (Exception e) { 1163 // OK: ignore per spec 1164 } 1165 } 1166 return list; 1167 } 1168 invoke(String actionName, Object[] params, String[] signature)1169 public Object invoke(String actionName, Object[] params, String[] signature) 1170 throws MBeanException, ReflectionException { 1171 if (params == null) 1172 params = new Object[0]; 1173 if (signature == null) 1174 signature = new String[0]; 1175 List<Method> methods = opMap.get(actionName); 1176 if (methods == null) { 1177 Exception x = new NoSuchMethodException(actionName); 1178 throw new MBeanException(x); 1179 } 1180 Method found = null; 1181 methodloop: 1182 for (Method m : methods) { 1183 Class<?>[] msig = m.getParameterTypes(); 1184 if (msig.length != signature.length) 1185 continue methodloop; 1186 for (int i = 0; i < msig.length; i++) { 1187 if (!msig[i].getName().equals(signature[i])) 1188 continue methodloop; 1189 } 1190 found = m; 1191 break methodloop; 1192 } 1193 if (found == null) { 1194 Exception x = new NoSuchMethodException( 1195 actionName + Arrays.toString(signature)); 1196 throw new MBeanException(x); 1197 } 1198 return invokeMethod(found, params); 1199 } 1200 getMBeanInfo()1201 public MBeanInfo getMBeanInfo() { 1202 // Attributes 1203 List<MBeanAttributeInfo> attrs = newList(); 1204 for (Map.Entry<String, AttrMethods> attr : attrMap.entrySet()) { 1205 String name = attr.getKey(); 1206 AttrMethods am = attr.getValue(); 1207 try { 1208 attrs.add(new MBeanAttributeInfo( 1209 name, name, am.getter, am.setter)); 1210 } catch (IntrospectionException e) { // grrr 1211 throw new RuntimeException(e); 1212 } 1213 } 1214 1215 // Operations 1216 List<MBeanOperationInfo> ops = newList(); 1217 for (Map.Entry<String, List<Method>> op : opMap.entrySet()) { 1218 String name = op.getKey(); 1219 List<Method> methods = op.getValue(); 1220 for (Method m : methods) 1221 ops.add(new MBeanOperationInfo(name, m)); 1222 } 1223 1224 // Constructors 1225 List<MBeanConstructorInfo> constrs = newList(); 1226 for (Constructor constr : std.getClass().getConstructors()) 1227 constrs.add(new MBeanConstructorInfo("Constructor", constr)); 1228 1229 // Notifications 1230 MBeanNotificationInfo[] notifs; 1231 if (std instanceof NotificationBroadcaster) 1232 notifs = ((NotificationBroadcaster) std).getNotificationInfo(); 1233 else 1234 notifs = null; 1235 1236 String className = std.getClass().getName(); 1237 return new MBeanInfo( 1238 className, className, 1239 attrs.toArray(new MBeanAttributeInfo[0]), 1240 constrs.toArray(new MBeanConstructorInfo[0]), 1241 ops.toArray(new MBeanOperationInfo[0]), 1242 notifs); 1243 } 1244 invokeMethod(Method m, Object... args)1245 private Object invokeMethod(Method m, Object... args) 1246 throws MBeanException, ReflectionException { 1247 return invokeSomething(m, std,args); 1248 } 1249 preRegister(MBeanServer server, ObjectName name)1250 public ObjectName preRegister(MBeanServer server, ObjectName name) 1251 throws Exception { 1252 return mbeanRegistration(std).preRegister(server, name); 1253 } 1254 postRegister(Boolean registrationDone)1255 public void postRegister(Boolean registrationDone) { 1256 mbeanRegistration(std).postRegister(registrationDone); 1257 } 1258 preDeregister()1259 public void preDeregister() throws Exception { 1260 mbeanRegistration(std).preDeregister(); 1261 } 1262 postDeregister()1263 public void postDeregister() { 1264 mbeanRegistration(std).postDeregister(); 1265 } 1266 getWrappedMBean()1267 public Object getWrappedMBean() { 1268 return std; 1269 } 1270 } 1271 standardToDynamic(Object std)1272 private DynamicMBean standardToDynamic(Object std) 1273 throws NotCompliantMBeanException { 1274 return new StandardWrapper(std); 1275 } 1276 1277 // private static class NotifWrapper 1278 // implements WrapDynamicMBean, NotificationEmitter { 1279 // private final DynamicMBean mbean; 1280 // 1281 // NotifWrapper(DynamicMBean mbean) { 1282 // this.mbean = mbean; 1283 // } 1284 // 1285 // public Object getAttribute(String attribute) 1286 // throws AttributeNotFoundException, MBeanException, ReflectionException { 1287 // return mbean.getAttribute(attribute); 1288 // } 1289 // 1290 // public void setAttribute(Attribute attribute) 1291 // throws AttributeNotFoundException, InvalidAttributeValueException, 1292 // MBeanException, ReflectionException { 1293 // mbean.setAttribute(attribute); 1294 // } 1295 // 1296 // public AttributeList getAttributes(String[] attributes) { 1297 // return mbean.getAttributes(attributes); 1298 // } 1299 // 1300 // public AttributeList setAttributes(AttributeList attributes) { 1301 // return mbean.setAttributes(attributes); 1302 // } 1303 // 1304 // public Object invoke( 1305 // String actionName, Object[] params, String[] signature) 1306 // throws MBeanException, ReflectionException { 1307 // return mbean.invoke(actionName, params, signature); 1308 // } 1309 // 1310 // public MBeanInfo getMBeanInfo() { 1311 // return mbean.getMBeanInfo(); 1312 // } 1313 // 1314 // public void removeNotificationListener( 1315 // NotificationListener listener, NotificationFilter filter, Object handback) 1316 // throws ListenerNotFoundException { 1317 // ((NotificationEmitter) mbean).removeNotificationListener( 1318 // listener, filter, handback); 1319 // // ClassCastException if MBean is not an emitter 1320 // } 1321 // 1322 // public void addNotificationListener( 1323 // NotificationListener listener, NotificationFilter filter, Object handback) 1324 // throws IllegalArgumentException { 1325 // ((NotificationBroadcaster) mbean).addNotificationListener( 1326 // listener, filter, handback); 1327 // } 1328 // 1329 // public void removeNotificationListener(NotificationListener listener) 1330 // throws ListenerNotFoundException { 1331 // ((NotificationBroadcaster) mbean).removeNotificationListener(listener); 1332 // } 1333 // 1334 // public MBeanNotificationInfo[] getNotificationInfo() { 1335 // return ((NotificationBroadcaster) mbean).getNotificationInfo(); 1336 // } 1337 // 1338 // public Object getWrappedMBean() { 1339 // return getUserMBean(mbean); 1340 // } 1341 // } 1342 invokeSomething( AccessibleObject ao, Object target, Object[] args)1343 private static Object invokeSomething( 1344 AccessibleObject ao, Object target, Object[] args) 1345 throws MBeanException, ReflectionException { 1346 try { 1347 if (ao instanceof Method) 1348 return ((Method) ao).invoke(target, args); 1349 else 1350 return ((Constructor) ao).newInstance(args); 1351 } catch (InvocationTargetException e) { 1352 try { 1353 throw e.getCause(); 1354 } catch (RuntimeException x) { 1355 throw new RuntimeMBeanException(x); 1356 } catch (Error x) { 1357 throw new RuntimeErrorException(x); 1358 } catch (Exception x) { 1359 throw new MBeanException(x); 1360 } catch (Throwable x) { 1361 throw new RuntimeException(x); // neither Error nor Exception! 1362 } 1363 } catch (Exception e) { 1364 throw new ReflectionException(e); 1365 } 1366 } 1367 getUserMBean(DynamicMBean mbean)1368 private static Object getUserMBean(DynamicMBean mbean) { 1369 if (mbean instanceof WrapDynamicMBean) 1370 return ((WrapDynamicMBean) mbean).getWrappedMBean(); 1371 return mbean; 1372 } 1373 getUserMBean(ObjectName name)1374 private Object getUserMBean(ObjectName name) 1375 throws InstanceNotFoundException { 1376 return getUserMBean(getMBean(name)); 1377 } 1378 1379 private static final MBeanRegistration noRegistration = 1380 new MBeanRegistration() { 1381 public ObjectName preRegister(MBeanServer server, ObjectName name) { 1382 return name; 1383 } 1384 1385 public void postRegister(Boolean registrationDone) { 1386 } 1387 1388 public void preDeregister() throws Exception { 1389 } 1390 1391 public void postDeregister() { 1392 } 1393 }; 1394 mbeanRegistration(Object object)1395 private static MBeanRegistration mbeanRegistration(Object object) { 1396 if (object instanceof MBeanRegistration) 1397 return (MBeanRegistration) object; 1398 else 1399 return noRegistration; 1400 } 1401 newList()1402 private static <E> List<E> newList() { 1403 return new ArrayList<E>(); 1404 } 1405 newMap()1406 private static <K, V> Map<K, V> newMap() { 1407 return new HashMap<K, V>(); 1408 } 1409 newSet()1410 private static <E> Set<E> newSet() { 1411 return new HashSet<E>(); 1412 } 1413 } 1414 } 1415