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