jdk/src/share/classes/com/sun/jmx/interceptor/MBeanServerSupport.java
changeset 1203 3e5496df0d2b
parent 1202 5a725d2f0daa
parent 1201 e87f9c042699
child 1211 b659a7cee935
equal deleted inserted replaced
1202:5a725d2f0daa 1203:3e5496df0d2b
     1 /*
       
     2  * Copyright 2007 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 package com.sun.jmx.interceptor;
       
    26 
       
    27 import com.sun.jmx.mbeanserver.Util;
       
    28 import java.io.ObjectInputStream;
       
    29 import java.util.Collections;
       
    30 import java.util.HashSet;
       
    31 import java.util.Set;
       
    32 import java.util.TreeSet;
       
    33 import java.util.logging.Level;
       
    34 import java.util.logging.Logger;
       
    35 import javax.management.Attribute;
       
    36 import javax.management.AttributeList;
       
    37 import javax.management.AttributeNotFoundException;
       
    38 import javax.management.DynamicMBean;
       
    39 import javax.management.DynamicWrapperMBean;
       
    40 import javax.management.InstanceAlreadyExistsException;
       
    41 import javax.management.InstanceNotFoundException;
       
    42 import javax.management.IntrospectionException;
       
    43 import javax.management.InvalidAttributeValueException;
       
    44 import javax.management.JMRuntimeException;
       
    45 import javax.management.ListenerNotFoundException;
       
    46 import javax.management.MBeanException;
       
    47 import javax.management.MBeanInfo;
       
    48 import javax.management.MBeanRegistrationException;
       
    49 import javax.management.MBeanServer;
       
    50 import javax.management.MalformedObjectNameException;
       
    51 import javax.management.NotCompliantMBeanException;
       
    52 import javax.management.NotificationBroadcaster;
       
    53 import javax.management.NotificationEmitter;
       
    54 import javax.management.NotificationFilter;
       
    55 import javax.management.NotificationListener;
       
    56 import javax.management.ObjectInstance;
       
    57 import javax.management.ObjectName;
       
    58 import javax.management.OperationsException;
       
    59 import javax.management.QueryEval;
       
    60 import javax.management.QueryExp;
       
    61 import javax.management.ReflectionException;
       
    62 import javax.management.RuntimeOperationsException;
       
    63 import javax.management.loading.ClassLoaderRepository;
       
    64 
       
    65 /**
       
    66  * <p>Base class for custom implementations of the {@link MBeanServer}
       
    67  * interface. The commonest use of this class is as the {@linkplain
       
    68  * JMXNamespace#getSourceServer() source server} for a {@link
       
    69  * JMXNamespace}, although this class can be used anywhere an {@code
       
    70  * MBeanServer} instance is required. Note that the usual ways to
       
    71  * obtain an {@code MBeanServer} instance are either to use {@link
       
    72  * java.lang.management.ManagementFactory#getPlatformMBeanServer()
       
    73  * ManagementFactory.getPlatformMBeanServer()} or to use the {@code
       
    74  * newMBeanServer} or {@code createMBeanServer} methods from {@link
       
    75  * javax.management.MBeanServerFactory MBeanServerFactory}. {@code
       
    76  * MBeanServerSupport} is for certain cases where those are not
       
    77  * appropriate.</p>
       
    78  *
       
    79  * <p>There are two main use cases for this class: <a
       
    80  * href="#special-purpose">special-purpose MBeanServer implementations</a>,
       
    81  * and <a href="#virtual">namespaces containing Virtual MBeans</a>. The next
       
    82  * sections explain these use cases.</p>
       
    83  *
       
    84  * <p>In the simplest case, a subclass needs to implement only two methods:</p>
       
    85  *
       
    86  * <ul>
       
    87  *     <li>
       
    88  *         {@link #getNames getNames} which returns the name of
       
    89  *         all MBeans handled by this {@code MBeanServer}.
       
    90  *     </li>
       
    91  *     <li>
       
    92  *         {@link #getDynamicMBeanFor getDynamicMBeanFor} which returns a
       
    93  *         {@link DynamicMBean} that can be used to invoke operations and
       
    94  *         obtain meta data (MBeanInfo) on a given MBean.
       
    95  *     </li>
       
    96  * </ul>
       
    97  *
       
    98  * <p>Subclasses can create such {@link DynamicMBean} MBeans on the fly - for
       
    99  * instance, using the class {@link javax.management.StandardMBean}, just for
       
   100  * the duration of an MBeanServer method call.</p>
       
   101  *
       
   102  * <h4 id="special-purpose">Special-purpose MBeanServer implementations</h4>
       
   103  *
       
   104  * <p>In some cases
       
   105  * the general-purpose {@code MBeanServer} that you get from
       
   106  * {@link javax.management.MBeanServerFactory MBeanServerFactory} is not
       
   107  * appropriate.  You might need different security checks, or you might
       
   108  * want a mock {@code MBeanServer} suitable for use in tests, or you might
       
   109  * want a simplified and optimized {@code MBeanServer} for a special purpose.</p>
       
   110  *
       
   111  * <p>As an example of a special-purpose {@code MBeanServer}, the class {@link
       
   112  * javax.management.QueryNotificationFilter QueryNotificationFilter} constructs
       
   113  * an {@code MBeanServer} instance every time it filters a notification,
       
   114  * with just one MBean that represents the notification. Although it could
       
   115  * use {@code MBeanServerFactory.newMBeanServer}, a special-purpose {@code
       
   116  * MBeanServer} will be quicker to create, use less memory, and have simpler
       
   117  * methods that execute faster.</p>
       
   118  *
       
   119  * <p>Here is an example of a special-purpose {@code MBeanServer}
       
   120  * implementation that contains exactly one MBean, which is specified at the
       
   121  * time of creation.</p>
       
   122  *
       
   123  * <pre>
       
   124  * public class SingletonMBeanServer extends MBeanServerSupport {
       
   125  *     private final ObjectName objectName;
       
   126  *     private final DynamicMBean mbean;
       
   127  *
       
   128  *     public SingletonMBeanServer(ObjectName objectName, DynamicMBean mbean) {
       
   129  *         this.objectName = objectName;
       
   130  *         this.mbean = mbean;
       
   131  *     }
       
   132  *
       
   133  *     &#64;Override
       
   134  *     protected {@code Set<ObjectName>} {@link #getNames getNames}() {
       
   135  *         return Collections.singleton(objectName);
       
   136  *     }
       
   137  *
       
   138  *     &#64;Override
       
   139  *     public DynamicMBean {@link #getDynamicMBeanFor
       
   140  *                                getDynamicMBeanFor}(ObjectName name)
       
   141  *             throws InstanceNotFoundException {
       
   142  *         if (objectName.equals(name))
       
   143  *             return mbean;
       
   144  *         else
       
   145  *             throw new InstanceNotFoundException(name);
       
   146  *     }
       
   147  * }
       
   148  * </pre>
       
   149  *
       
   150  * <p>Using this class, you could make an {@code MBeanServer} that contains
       
   151  * a {@link javax.management.timer.Timer Timer} MBean like this:</p>
       
   152  *
       
   153  * <pre>
       
   154  *     Timer timer = new Timer();
       
   155  *     DynamicMBean mbean = new {@link javax.management.StandardMBean
       
   156  *                                     StandardMBean}(timer, TimerMBean.class);
       
   157  *     ObjectName name = new ObjectName("com.example:type=Timer");
       
   158  *     MBeanServer timerMBS = new SingletonMBeanServer(name, mbean);
       
   159  * </pre>
       
   160  *
       
   161  * <p>When {@code getDynamicMBeanFor} always returns the same object for the
       
   162  * same name, as here, notifications work in the expected way: if the object
       
   163  * is a {@link NotificationEmitter} then listeners can be added using
       
   164  * {@link MBeanServer#addNotificationListener(ObjectName, NotificationListener,
       
   165  * NotificationFilter, Object) MBeanServer.addNotificationListener}.  If
       
   166  * {@code getDynamicMBeanFor} does not always return the same object for the
       
   167  * same name, more work is needed to make notifications work, as described
       
   168  * <a href="#notifs">below</a>.</p>
       
   169  *
       
   170  * <h4 id="virtual">Namespaces containing Virtual MBeans</h4>
       
   171  *
       
   172  * <p>Virtual MBeans are MBeans that do not exist as Java objects,
       
   173  * except transiently while they are being accessed.  This is useful when
       
   174  * there might be very many of them, or when keeping track of their creation
       
   175  * and deletion might be expensive or hard.  For example, you might have one
       
   176  * MBean per system process.  With an ordinary {@code MBeanServer}, you would
       
   177  * have to list the system processes in order to create an MBean object for
       
   178  * each one, and you would have to track the arrival and departure of system
       
   179  * processes in order to create or delete the corresponding MBeans.  With
       
   180  * Virtual MBeans, you only need the MBean for a given process at the exact
       
   181  * point where it is referenced with a call such as
       
   182  * {@link MBeanServer#getAttribute MBeanServer.getAttribute}.</p>
       
   183  *
       
   184  * <p>Here is an example of an {@code MBeanServer} implementation that has
       
   185  * one MBean for every system property.  The system property {@code "java.home"}
       
   186  * is represented by the MBean called {@code
       
   187  * com.example:type=Property,name="java.home"}, with an attribute called
       
   188  * {@code Value} that is the value of the property.</p>
       
   189  *
       
   190  * <pre>
       
   191  * public interface PropertyMBean {
       
   192  *     public String getValue();
       
   193  * }
       
   194  *
       
   195  * <a name="PropsMBS"></a>public class PropsMBS extends MBeanServerSupport {
       
   196  *     private static ObjectName newObjectName(String name) {
       
   197  *         try {
       
   198  *             return new ObjectName(name);
       
   199  *         } catch (MalformedObjectNameException e) {
       
   200  *             throw new AssertionError(e);
       
   201  *         }
       
   202  *     }
       
   203  *
       
   204  *     public static class PropertyImpl implements PropertyMBean {
       
   205  *         private final String name;
       
   206  *
       
   207  *         public PropertyImpl(String name) {
       
   208  *             this.name = name;
       
   209  *         }
       
   210  *
       
   211  *         public String getValue() {
       
   212  *             return System.getProperty(name);
       
   213  *         }
       
   214  *     }
       
   215  *
       
   216  *     &#64;Override
       
   217  *     public DynamicMBean {@link #getDynamicMBeanFor
       
   218  *                                getDynamicMBeanFor}(ObjectName name)
       
   219  *             throws InstanceNotFoundException {
       
   220  *
       
   221  *         // Check that the name is a legal one for a Property MBean
       
   222  *         ObjectName namePattern = newObjectName(
       
   223  *                     "com.example:type=Property,name=\"*\"");
       
   224  *         if (!namePattern.apply(name))
       
   225  *             throw new InstanceNotFoundException(name);
       
   226  *
       
   227  *         // Extract the name of the property that the MBean corresponds to
       
   228  *         String propName = ObjectName.unquote(name.getKeyProperty("name"));
       
   229  *         if (System.getProperty(propName) == null)
       
   230  *             throw new InstanceNotFoundException(name);
       
   231  *
       
   232  *         // Construct and return a transient MBean object
       
   233  *         PropertyMBean propMBean = new PropertyImpl(propName);
       
   234  *         return new StandardMBean(propMBean, PropertyMBean.class, false);
       
   235  *     }
       
   236  *
       
   237  *     &#64;Override
       
   238  *     protected {@code Set<ObjectName>} {@link #getNames getNames}() {
       
   239  *         {@code Set<ObjectName> names = new TreeSet<ObjectName>();}
       
   240  *         Properties props = System.getProperties();
       
   241  *         for (String propName : props.stringPropertyNames()) {
       
   242  *             ObjectName objectName = newObjectName(
       
   243  *                     "com.example:type=Property,name=" +
       
   244  *                     ObjectName.quote(propName));
       
   245  *             names.add(objectName);
       
   246  *         }
       
   247  *         return names;
       
   248  *     }
       
   249  * }
       
   250  * </pre>
       
   251  *
       
   252  * <p id="virtual-notif-example">Because the {@code getDynamicMBeanFor} method
       
   253  * returns a different object every time it is called, the default handling
       
   254  * of notifications will not work, as explained <a href="#notifs">below</a>.
       
   255  * In this case it does not matter, because the object returned by {@code
       
   256  * getDynamicMBeanFor} is not a {@code NotificationEmitter}, so {@link
       
   257  * MBeanServer#addNotificationListener(ObjectName, NotificationListener,
       
   258  * NotificationFilter, Object) MBeanServer.addNotificationListener} will
       
   259  * always fail. But if we wanted to extend {@code PropsMBS} so that the MBean
       
   260  * for property {@code "foo"} emitted a notification every time that property
       
   261  * changed, we would need to do it as shown below. (Because there is no API to
       
   262  * be informed when a property changes, this code assumes that some other code
       
   263  * calls the {@code propertyChanged} method every time a property changes.)</p>
       
   264  *
       
   265  * <pre>
       
   266  * public class PropsMBS {
       
   267  *     ...as <a href="#PropsMBS">above</a>...
       
   268  *
       
   269  *     private final {@link VirtualEventManager} vem = new VirtualEventManager();
       
   270  *
       
   271  *     &#64;Override
       
   272  *     public NotificationEmitter {@link #getNotificationEmitterFor
       
   273  *                                       getNotificationEmitterFor}(
       
   274  *             ObjectName name) throws InstanceNotFoundException {
       
   275  *         getDynamicMBeanFor(name);  // check that the name is valid
       
   276  *         return vem.{@link VirtualEventManager#getNotificationEmitterFor
       
   277  *                           getNotificationEmitterFor}(name);
       
   278  *     }
       
   279  *
       
   280  *     public void propertyChanged(String name, String newValue) {
       
   281  *         ObjectName objectName = newObjectName(
       
   282  *                 "com.example:type=Property,name=" + ObjectName.quote(name));
       
   283  *         Notification n = new Notification(
       
   284  *                 "com.example.property.changed", objectName, 0L,
       
   285  *                 "Property " + name + " changed");
       
   286  *         n.setUserData(newValue);
       
   287  *         vem.{@link VirtualEventManager#publish publish}(objectName, n);
       
   288  *     }
       
   289  * }
       
   290  * </pre>
       
   291  *
       
   292  * <h4 id="creation">MBean creation and deletion</h4>
       
   293  *
       
   294  * <p>MBean creation through {@code MBeanServer.createMBean} is disabled
       
   295  * by default. Subclasses which need to support MBean creation
       
   296  * through {@code createMBean} need to implement a single method {@link
       
   297  * #createMBean(String, ObjectName, ObjectName, Object[], String[],
       
   298  * boolean)}.</p>
       
   299  *
       
   300  * <p>Similarly MBean registration and unregistration through {@code
       
   301  * registerMBean} and {@code unregisterMBean} are disabled by default.
       
   302  * Subclasses which need to support MBean registration and
       
   303  * unregistration will need to implement {@link #registerMBean registerMBean}
       
   304  * and {@link #unregisterMBean unregisterMBean}.</p>
       
   305  *
       
   306  * <h4 id="notifs">Notifications</h4>
       
   307  *
       
   308  * <p>By default {@link MBeanServer#addNotificationListener(ObjectName,
       
   309  * NotificationListener, NotificationFilter, Object) addNotificationListener}
       
   310  * is accepted for an MBean <em>{@code name}</em> if {@link #getDynamicMBeanFor
       
   311  * getDynamicMBeanFor}<code>(<em>name</em>)</code> returns an object that is a
       
   312  * {@link NotificationEmitter}.  That is appropriate if
       
   313  * {@code getDynamicMBeanFor}<code>(<em>name</em>)</code> always returns the
       
   314  * same object for the same <em>{@code name}</em>.  But with
       
   315  * Virtual MBeans, every call to {@code getDynamicMBeanFor} returns a new object,
       
   316  * which is discarded as soon as the MBean request has finished.
       
   317  * So a listener added to that object would be immediately forgotten.</p>
       
   318  *
       
   319  * <p>The simplest way for a subclass that defines Virtual MBeans
       
   320  * to support notifications is to create a private {@link VirtualEventManager}
       
   321  * and override the method {@link
       
   322  * #getNotificationEmitterFor getNotificationEmitterFor} as follows:</p>
       
   323  *
       
   324  * <pre>
       
   325  *     private final VirtualEventManager vem = new VirtualEventManager();
       
   326  *
       
   327  *     &#64;Override
       
   328  *     public NotificationEmitter getNotificationEmitterFor(
       
   329  *             ObjectName name) throws InstanceNotFoundException {
       
   330  *         // Check that the name is a valid Virtual MBean.
       
   331  *         // This is the easiest way to do that, but not always the
       
   332  *         // most efficient:
       
   333  *         getDynamicMBeanFor(name);
       
   334  *
       
   335  *         // Return an object that supports add/removeNotificationListener
       
   336  *         // through the VirtualEventManager.
       
   337  *         return vem.getNotificationEmitterFor(name);
       
   338  *     }
       
   339  * </pre>
       
   340  *
       
   341  * <p>A notification <em>{@code n}</em> can then be sent from the Virtual MBean
       
   342  * called <em>{@code name}</em> by calling {@link VirtualEventManager#publish
       
   343  * vem.publish}<code>(<em>name</em>, <em>n</em>)</code>.  See the example
       
   344  * <a href="#virtual-notif-example">above</a>.</p>
       
   345  *
       
   346  * @since Java SE 7
       
   347  */
       
   348 public abstract class MBeanServerSupport implements MBeanServer {
       
   349 
       
   350     /**
       
   351      * A logger for this class.
       
   352      */
       
   353     private static final Logger LOG =
       
   354             Logger.getLogger(MBeanServerSupport.class.getName());
       
   355 
       
   356     /**
       
   357      * <p>Make a new {@code MBeanServerSupport} instance.</p>
       
   358      */
       
   359     protected MBeanServerSupport() {
       
   360     }
       
   361 
       
   362     /**
       
   363      * <p>Returns a dynamically created handle that makes it possible to
       
   364      * access the named MBean for the duration of a method call.</p>
       
   365      *
       
   366      * <p>An easy way to create such a {@link DynamicMBean} handle is, for
       
   367      * instance, to create a temporary MXBean instance and to wrap it in
       
   368      * an instance of
       
   369      * {@link javax.management.StandardMBean}.
       
   370      * This handle should remain valid for the duration of the call
       
   371      * but can then be discarded.</p>
       
   372      * @param name the name of the MBean for which a request was received.
       
   373      * @return a {@link DynamicMBean} handle that can be used to invoke
       
   374      * operations on the named MBean.
       
   375      * @throws InstanceNotFoundException if no such MBean is supposed
       
   376      *         to exist.
       
   377      */
       
   378     public abstract DynamicMBean getDynamicMBeanFor(ObjectName name)
       
   379                         throws InstanceNotFoundException;
       
   380 
       
   381     /**
       
   382      * <p>Subclasses should implement this method to return
       
   383      * the names of all MBeans handled by this object instance.</p>
       
   384      *
       
   385      * <p>The object returned by getNames() should be safely {@linkplain
       
   386      * Set#iterator iterable} even in the presence of other threads that may
       
   387      * cause the set of names to change. Typically this means one of the
       
   388      * following:</p>
       
   389      *
       
   390      * <ul>
       
   391      * <li>the returned set of names is always the same; or
       
   392      * <li>the returned set of names is an object such as a {@link
       
   393      * java.util.concurrent.CopyOnWriteArraySet CopyOnWriteArraySet} that is
       
   394      * safely iterable even if the set is changed by other threads; or
       
   395      * <li>a new Set is constructed every time this method is called.
       
   396      * </ul>
       
   397      *
       
   398      * @return the names of all MBeans handled by this object.
       
   399      */
       
   400     protected abstract Set<ObjectName> getNames();
       
   401 
       
   402     /**
       
   403      * <p>List names matching the given pattern.
       
   404      * The default implementation of this method calls {@link #getNames()}
       
   405      * and returns the subset of those names matching {@code pattern}.</p>
       
   406      *
       
   407      * @param pattern an ObjectName pattern
       
   408      * @return the list of MBean names that match the given pattern.
       
   409      */
       
   410     protected Set<ObjectName> getMatchingNames(ObjectName pattern) {
       
   411         return Util.filterMatchingNames(pattern, getNames());
       
   412     }
       
   413 
       
   414     /**
       
   415      * <p>Returns a {@link NotificationEmitter} which can be used to
       
   416      * subscribe or unsubscribe for notifications with the named
       
   417      * mbean.</p>
       
   418      *
       
   419      * <p>The default implementation of this method calls {@link
       
   420      * #getDynamicMBeanFor getDynamicMBeanFor(name)} and returns that object
       
   421      * if it is a {@code NotificationEmitter}, otherwise null. See <a
       
   422      * href="#notifs">above</a> for further discussion of notification
       
   423      * handling.</p>
       
   424      *
       
   425      * @param name The name of the MBean whose notifications are being
       
   426      * subscribed, or unsuscribed.
       
   427      *
       
   428      * @return A {@link NotificationEmitter} that can be used to subscribe or
       
   429      * unsubscribe for notifications emitted by the named MBean, or {@code
       
   430      * null} if the MBean does not emit notifications and should not be
       
   431      * considered as a {@code NotificationEmitter}.
       
   432      *
       
   433      * @throws InstanceNotFoundException if {@code name} is not the name of
       
   434      * an MBean in this {@code MBeanServer}.
       
   435      */
       
   436     public NotificationEmitter getNotificationEmitterFor(ObjectName name)
       
   437             throws InstanceNotFoundException {
       
   438         DynamicMBean mbean = getDynamicMBeanFor(name);
       
   439         if (mbean instanceof NotificationEmitter)
       
   440             return (NotificationEmitter) mbean;
       
   441         else
       
   442             return null;
       
   443     }
       
   444 
       
   445     private NotificationEmitter getNonNullNotificationEmitterFor(
       
   446             ObjectName name)
       
   447             throws InstanceNotFoundException {
       
   448         NotificationEmitter emitter = getNotificationEmitterFor(name);
       
   449         if (emitter == null) {
       
   450             IllegalArgumentException iae = new IllegalArgumentException(
       
   451                     "Not a NotificationEmitter: " + name);
       
   452             throw new RuntimeOperationsException(iae);
       
   453         }
       
   454         return emitter;
       
   455     }
       
   456 
       
   457     /**
       
   458      * <p>Creates a new MBean in the MBean name space.
       
   459      * This operation is not supported in this base class implementation.</p>
       
   460      * The default implementation of this method always throws an {@link
       
   461      * UnsupportedOperationException}
       
   462      * wrapped in a {@link RuntimeOperationsException}.</p>
       
   463      *
       
   464      * <p>Subclasses may redefine this method to provide an implementation.
       
   465      * All the various flavors of {@code MBeanServer.createMBean} methods
       
   466      * will eventually call this method. A subclass that wishes to
       
   467      * support MBean creation through {@code createMBean} thus only
       
   468      * needs to provide an implementation for this one method.
       
   469      *
       
   470      * @param className The class name of the MBean to be instantiated.
       
   471      * @param name The object name of the MBean. May be null.
       
   472      * @param params An array containing the parameters of the
       
   473      * constructor to be invoked.
       
   474      * @param signature An array containing the signature of the
       
   475      * constructor to be invoked.
       
   476      * @param loaderName The object name of the class loader to be used.
       
   477      * @param useCLR This parameter is {@code true} when this method
       
   478      *        is called from one of the {@code MBeanServer.createMBean} methods
       
   479      *        whose signature does not include the {@code ObjectName} of an
       
   480      *        MBean class loader to use for loading the MBean class.
       
   481      *
       
   482      * @return An <CODE>ObjectInstance</CODE>, containing the
       
   483      * <CODE>ObjectName</CODE> and the Java class name of the newly
       
   484      * instantiated MBean.  If the contained <code>ObjectName</code>
       
   485      * is <code>n</code>, the contained Java class name is
       
   486      * <code>{@link javax.management.MBeanServer#getMBeanInfo
       
   487      * getMBeanInfo(n)}.getClassName()</code>.
       
   488      *
       
   489      * @exception ReflectionException Wraps a
       
   490      * <CODE>java.lang.ClassNotFoundException</CODE> or a
       
   491      * <CODE>java.lang.Exception</CODE> that occurred when trying to
       
   492      * invoke the MBean's constructor.
       
   493      * @exception InstanceAlreadyExistsException The MBean is already
       
   494      * under the control of the MBean server.
       
   495      * @exception MBeanRegistrationException The
       
   496      * <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
       
   497      * interface) method of the MBean has thrown an exception. The
       
   498      * MBean will not be registered.
       
   499      * @exception MBeanException The constructor of the MBean has
       
   500      * thrown an exception
       
   501      * @exception NotCompliantMBeanException This class is not a JMX
       
   502      * compliant MBean
       
   503      * @exception InstanceNotFoundException The specified class loader
       
   504      * is not registered in the MBean server.
       
   505      * @exception RuntimeOperationsException Wraps either:
       
   506      * <ul>
       
   507      * <li>a <CODE>java.lang.IllegalArgumentException</CODE>: The className
       
   508      * passed in parameter is null, the <CODE>ObjectName</CODE> passed in
       
   509      * parameter contains a pattern or no <CODE>ObjectName</CODE> is specified
       
   510      * for the MBean; or</li>
       
   511      * <li>an {@code UnsupportedOperationException} if creating MBeans is not
       
   512      * supported by this {@code MBeanServer} implementation.
       
   513      * </ul>
       
   514      */
       
   515     public ObjectInstance createMBean(String className,
       
   516             ObjectName name, ObjectName loaderName, Object[] params,
       
   517             String[] signature, boolean useCLR)
       
   518             throws ReflectionException, InstanceAlreadyExistsException,
       
   519             MBeanRegistrationException, MBeanException,
       
   520             NotCompliantMBeanException, InstanceNotFoundException {
       
   521         throw newUnsupportedException("createMBean");
       
   522     }
       
   523 
       
   524 
       
   525     /**
       
   526      * <p>Attempts to determine whether the named MBean should be
       
   527      * considered as an instance of a given class.  The default implementation
       
   528      * of this method calls {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}
       
   529      * to get an MBean object.  Then its behaviour is the same as the standard
       
   530      * {@link MBeanServer#isInstanceOf MBeanServer.isInstanceOf} method.</p>
       
   531      *
       
   532      * {@inheritDoc}
       
   533      */
       
   534     public boolean isInstanceOf(ObjectName name, String className)
       
   535         throws InstanceNotFoundException {
       
   536 
       
   537         final DynamicMBean instance = nonNullMBeanFor(name);
       
   538 
       
   539         try {
       
   540             final String mbeanClassName = instance.getMBeanInfo().getClassName();
       
   541 
       
   542             if (mbeanClassName.equals(className))
       
   543                 return true;
       
   544 
       
   545             final Object resource;
       
   546             final ClassLoader cl;
       
   547             if (instance instanceof DynamicWrapperMBean) {
       
   548                 DynamicWrapperMBean d = (DynamicWrapperMBean) instance;
       
   549                 resource = d.getWrappedObject();
       
   550                 cl = d.getWrappedClassLoader();
       
   551             } else {
       
   552                 resource = instance;
       
   553                 cl = instance.getClass().getClassLoader();
       
   554             }
       
   555 
       
   556             final Class<?> classNameClass = Class.forName(className, false, cl);
       
   557 
       
   558             if (classNameClass.isInstance(resource))
       
   559                 return true;
       
   560 
       
   561             if (classNameClass == NotificationBroadcaster.class ||
       
   562                     classNameClass == NotificationEmitter.class) {
       
   563                 try {
       
   564                     getNotificationEmitterFor(name);
       
   565                     return true;
       
   566                 } catch (Exception x) {
       
   567                     LOG.finest("MBean " + name +
       
   568                             " is not a notification emitter. Ignoring: "+x);
       
   569                     return false;
       
   570                 }
       
   571             }
       
   572 
       
   573             final Class<?> resourceClass = Class.forName(mbeanClassName, false, cl);
       
   574             return classNameClass.isAssignableFrom(resourceClass);
       
   575         } catch (Exception x) {
       
   576             /* Could be SecurityException or ClassNotFoundException */
       
   577             LOG.logp(Level.FINEST,
       
   578                     MBeanServerSupport.class.getName(),
       
   579                     "isInstanceOf", "Exception calling isInstanceOf", x);
       
   580             return false;
       
   581         }
       
   582     }
       
   583 
       
   584     /**
       
   585      * {@inheritDoc}
       
   586      *
       
   587      * <p>The default implementation of this method returns the string
       
   588      * "DefaultDomain".</p>
       
   589      */
       
   590     public String getDefaultDomain() {
       
   591         return "DefaultDomain";
       
   592     }
       
   593 
       
   594     /**
       
   595      * {@inheritDoc}
       
   596      *
       
   597      * <p>The default implementation of this method returns
       
   598      * {@link #getNames()}.size().</p>
       
   599      */
       
   600     public Integer getMBeanCount() {
       
   601         return getNames().size();
       
   602     }
       
   603 
       
   604     /**
       
   605      * {@inheritDoc}
       
   606      *
       
   607      * <p>The default implementation of this method first calls {@link #getNames
       
   608      * getNames()} to get a list of all MBean names,
       
   609      * and from this set of names, derives the set of domains which contain
       
   610      * MBeans.</p>
       
   611      */
       
   612     public String[] getDomains() {
       
   613         final Set<ObjectName> names = getNames();
       
   614         final Set<String> res = new TreeSet<String>();
       
   615         for (ObjectName n : names) {
       
   616             if (n == null) continue; // not allowed but you never know.
       
   617             res.add(n.getDomain());
       
   618         }
       
   619         return res.toArray(new String[res.size()]);
       
   620     }
       
   621 
       
   622 
       
   623     /**
       
   624      * {@inheritDoc}
       
   625      *
       
   626      * <p>The default implementation of this method will first
       
   627      * call {@link
       
   628      *    #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle
       
   629      * to the named MBean,
       
   630      * and then call {@link DynamicMBean#getAttribute getAttribute}
       
   631      * on that {@link DynamicMBean} handle.</p>
       
   632      *
       
   633      * @throws RuntimeOperationsException {@inheritDoc}
       
   634      */
       
   635     public Object getAttribute(ObjectName name, String attribute)
       
   636         throws MBeanException, AttributeNotFoundException,
       
   637                InstanceNotFoundException, ReflectionException {
       
   638         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   639         return mbean.getAttribute(attribute);
       
   640     }
       
   641 
       
   642     /**
       
   643      * {@inheritDoc}
       
   644      *
       
   645      * <p>The default implementation of this method will first
       
   646      * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}
       
   647      * to obtain a handle to the named MBean,
       
   648      * and then call {@link DynamicMBean#setAttribute setAttribute}
       
   649      * on that {@link DynamicMBean} handle.</p>
       
   650      *
       
   651      * @throws RuntimeOperationsException {@inheritDoc}
       
   652      */
       
   653     public void setAttribute(ObjectName name, Attribute attribute)
       
   654         throws InstanceNotFoundException, AttributeNotFoundException,
       
   655             InvalidAttributeValueException, MBeanException,
       
   656             ReflectionException {
       
   657         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   658         mbean.setAttribute(attribute);
       
   659     }
       
   660 
       
   661     /**
       
   662      * {@inheritDoc}
       
   663      *
       
   664      * <p>The default implementation of this method will first
       
   665      * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
       
   666      * handle to the named MBean,
       
   667      * and then call {@link DynamicMBean#getAttributes getAttributes}
       
   668      * on that {@link DynamicMBean} handle.</p>
       
   669      *
       
   670      * @throws RuntimeOperationsException {@inheritDoc}
       
   671      */
       
   672     public AttributeList getAttributes(ObjectName name,
       
   673             String[] attributes) throws InstanceNotFoundException,
       
   674             ReflectionException {
       
   675         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   676         return mbean.getAttributes(attributes);
       
   677     }
       
   678 
       
   679     /**
       
   680      * {@inheritDoc}
       
   681      *
       
   682      * <p>The default implementation of this method will first
       
   683      * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
       
   684      * handle to the named MBean,
       
   685      * and then call {@link DynamicMBean#setAttributes setAttributes}
       
   686      * on that {@link DynamicMBean} handle.</p>
       
   687      *
       
   688      * @throws RuntimeOperationsException {@inheritDoc}
       
   689      */
       
   690     public AttributeList setAttributes(ObjectName name, AttributeList attributes)
       
   691         throws InstanceNotFoundException, ReflectionException {
       
   692         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   693         return mbean.setAttributes(attributes);
       
   694     }
       
   695 
       
   696     /**
       
   697      * {@inheritDoc}
       
   698      *
       
   699      * <p>The default implementation of this method will first
       
   700      * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
       
   701      * handle to the named MBean,
       
   702      * and then call {@link DynamicMBean#invoke invoke}
       
   703      * on that {@link DynamicMBean} handle.</p>
       
   704      */
       
   705     public Object invoke(ObjectName name, String operationName,
       
   706                 Object[] params, String[] signature)
       
   707                 throws InstanceNotFoundException, MBeanException,
       
   708                        ReflectionException {
       
   709         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   710         return mbean.invoke(operationName, params, signature);
       
   711     }
       
   712 
       
   713     /**
       
   714      * {@inheritDoc}
       
   715      *
       
   716      * <p>The default implementation of this method will first
       
   717      * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
       
   718      * handle to the named MBean,
       
   719      * and then call {@link DynamicMBean#getMBeanInfo getMBeanInfo}
       
   720      * on that {@link DynamicMBean} handle.</p>
       
   721      */
       
   722     public MBeanInfo getMBeanInfo(ObjectName name)
       
   723         throws InstanceNotFoundException, IntrospectionException,
       
   724                ReflectionException {
       
   725         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   726         return mbean.getMBeanInfo();
       
   727    }
       
   728 
       
   729     /**
       
   730      * {@inheritDoc}
       
   731      *
       
   732      * <p>The default implementation of this method will call
       
   733      * {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}.<!--
       
   734      * -->{@link DynamicMBean#getMBeanInfo getMBeanInfo()}.<!--
       
   735      * -->{@link MBeanInfo#getClassName getClassName()} to get the
       
   736      * class name to combine with {@code name} to produce a new
       
   737      * {@code ObjectInstance}.</p>
       
   738      */
       
   739     public ObjectInstance getObjectInstance(ObjectName name)
       
   740             throws InstanceNotFoundException {
       
   741         final DynamicMBean mbean = nonNullMBeanFor(name);
       
   742         final String className = mbean.getMBeanInfo().getClassName();
       
   743         return new ObjectInstance(name, className);
       
   744     }
       
   745 
       
   746     /**
       
   747      * {@inheritDoc}
       
   748      *
       
   749      * <p>The default implementation of this method will first call {@link
       
   750      * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle to the
       
   751      * named MBean. If {@code getDynamicMBeanFor} returns an object, {@code
       
   752      * isRegistered} will return true. If {@code getDynamicMBeanFor} returns
       
   753      * null or throws {@link InstanceNotFoundException}, {@code isRegistered}
       
   754      * will return false.</p>
       
   755      *
       
   756      * @throws RuntimeOperationsException {@inheritDoc}
       
   757      */
       
   758     public boolean isRegistered(ObjectName name) {
       
   759         try {
       
   760             final DynamicMBean mbean = getDynamicMBeanFor(name);
       
   761             return mbean!=null;
       
   762         } catch (InstanceNotFoundException x) {
       
   763             if (LOG.isLoggable(Level.FINEST))
       
   764                 LOG.finest("MBean "+name+" is not registered: "+x);
       
   765             return false;
       
   766         }
       
   767     }
       
   768 
       
   769 
       
   770     /**
       
   771      * {@inheritDoc}
       
   772      *
       
   773      * <p>The default implementation of this method will first
       
   774      * call {@link #queryNames queryNames}
       
   775      * to get a list of all matching MBeans, and then, for each returned name,
       
   776      * call {@link #getObjectInstance getObjectInstance(name)}.</p>
       
   777      */
       
   778     public Set<ObjectInstance> queryMBeans(ObjectName pattern, QueryExp query) {
       
   779         final Set<ObjectName> names = queryNames(pattern, query);
       
   780         if (names.isEmpty()) return Collections.emptySet();
       
   781         final Set<ObjectInstance> mbeans = new HashSet<ObjectInstance>();
       
   782         for (ObjectName name : names) {
       
   783             try {
       
   784                 mbeans.add(getObjectInstance(name));
       
   785             } catch (SecurityException x) { // DLS: OK
       
   786                 continue;
       
   787             } catch (InstanceNotFoundException x) { // DLS: OK
       
   788                 continue;
       
   789             }
       
   790         }
       
   791         return mbeans;
       
   792     }
       
   793 
       
   794     /**
       
   795      * {@inheritDoc}
       
   796      *
       
   797      * <p>The default implementation of this method calls {@link #getMatchingNames
       
   798      * getMatchingNames(pattern)} to obtain a list of MBeans matching
       
   799      * the given name pattern. If the {@code query} parameter is null,
       
   800      * this will be the result. Otherwise, it will evaluate the
       
   801      * {@code query} parameter for each of the returned names, exactly
       
   802      * as an {@code MBeanServer} would. This might result in
       
   803      * {@link #getDynamicMBeanFor getDynamicMBeanFor} being called
       
   804      * several times for each returned name.</p>
       
   805      */
       
   806     public Set<ObjectName> queryNames(ObjectName pattern, QueryExp query) {
       
   807         try {
       
   808             final Set<ObjectName> res = getMatchingNames(pattern);
       
   809             return filterListOfObjectNames(res, query);
       
   810         } catch (Exception x) {
       
   811             LOG.fine("Unexpected exception raised in queryNames: "+x);
       
   812             LOG.log(Level.FINEST, "Unexpected exception raised in queryNames", x);
       
   813         }
       
   814         // We reach here only when an exception was raised.
       
   815         //
       
   816         return Collections.emptySet();
       
   817     }
       
   818 
       
   819     private final static boolean apply(final QueryExp query,
       
   820                   final ObjectName on,
       
   821                   final MBeanServer srv) {
       
   822         boolean res = false;
       
   823         MBeanServer oldServer = QueryEval.getMBeanServer();
       
   824         query.setMBeanServer(srv);
       
   825         try {
       
   826             res = query.apply(on);
       
   827         } catch (Exception e) {
       
   828             LOG.finest("QueryExp.apply threw exception, returning false." +
       
   829                     " Cause: "+e);
       
   830             res = false;
       
   831         } finally {
       
   832            /*
       
   833             * query.setMBeanServer is probably
       
   834             * QueryEval.setMBeanServer so put back the old
       
   835             * value.  Since that method uses a ThreadLocal
       
   836             * variable, this code is only needed for the
       
   837             * unusual case where the user creates a custom
       
   838             * QueryExp that calls a nested query on another
       
   839             * MBeanServer.
       
   840             */
       
   841             query.setMBeanServer(oldServer);
       
   842         }
       
   843         return res;
       
   844     }
       
   845 
       
   846     /**
       
   847      * Filters a {@code Set<ObjectName>} according to a pattern and a query.
       
   848      * This might be quite inefficient for virtual name spaces.
       
   849      */
       
   850     Set<ObjectName>
       
   851             filterListOfObjectNames(Set<ObjectName> list,
       
   852                                     QueryExp query) {
       
   853         if (list.isEmpty() || query == null)
       
   854             return list;
       
   855 
       
   856         // create a new result set
       
   857         final Set<ObjectName> result = new HashSet<ObjectName>();
       
   858 
       
   859         for (ObjectName on : list) {
       
   860             // if on doesn't match query exclude it.
       
   861             if (apply(query, on, this))
       
   862                 result.add(on);
       
   863         }
       
   864         return result;
       
   865     }
       
   866 
       
   867 
       
   868     // Don't use {@inheritDoc}, because we don't want to say that the
       
   869     // MBeanServer replaces a reference to the MBean by its ObjectName.
       
   870     /**
       
   871      * <p>Adds a listener to a registered MBean. A notification emitted by
       
   872      * the MBean will be forwarded to the listener.</p>
       
   873      *
       
   874      * <p>This implementation calls
       
   875      * {@link #getNotificationEmitterFor getNotificationEmitterFor}
       
   876      * and invokes {@code addNotificationListener} on the
       
   877      * {@link NotificationEmitter} it returns.
       
   878      *
       
   879      * @see #getDynamicMBeanFor getDynamicMBeanFor
       
   880      * @see #getNotificationEmitterFor getNotificationEmitterFor
       
   881      */
       
   882     public void addNotificationListener(ObjectName name,
       
   883             NotificationListener listener, NotificationFilter filter,
       
   884             Object handback) throws InstanceNotFoundException {
       
   885         final NotificationEmitter emitter =
       
   886                 getNonNullNotificationEmitterFor(name);
       
   887         emitter.addNotificationListener(listener, filter, handback);
       
   888     }
       
   889 
       
   890     /**
       
   891      * {@inheritDoc}
       
   892      *
       
   893      * <p>This implementation calls
       
   894      * {@link #getNotificationEmitterFor getNotificationEmitterFor}
       
   895      * and invokes {@code removeNotificationListener} on the
       
   896      * {@link NotificationEmitter} it returns.
       
   897      * @see #getDynamicMBeanFor getDynamicMBeanFor
       
   898      * @see #getNotificationEmitterFor getNotificationEmitterFor
       
   899      */
       
   900     public void removeNotificationListener(ObjectName name,
       
   901             NotificationListener listener)
       
   902             throws InstanceNotFoundException, ListenerNotFoundException {
       
   903         final NotificationEmitter emitter =
       
   904                 getNonNullNotificationEmitterFor(name);
       
   905         emitter.removeNotificationListener(listener);
       
   906     }
       
   907 
       
   908     /**
       
   909      * {@inheritDoc}
       
   910      *
       
   911      * <p>This implementation calls
       
   912      * {@link #getNotificationEmitterFor getNotificationEmitterFor}
       
   913      * and invokes {@code removeNotificationListener} on the
       
   914      * {@link NotificationEmitter} it returns.
       
   915      * @see #getDynamicMBeanFor getDynamicMBeanFor
       
   916      * @see #getNotificationEmitterFor getNotificationEmitterFor
       
   917      */
       
   918     public void removeNotificationListener(ObjectName name,
       
   919             NotificationListener listener, NotificationFilter filter,
       
   920             Object handback)
       
   921             throws InstanceNotFoundException, ListenerNotFoundException {
       
   922         NotificationEmitter emitter =
       
   923                 getNonNullNotificationEmitterFor(name);
       
   924         emitter.removeNotificationListener(listener);
       
   925     }
       
   926 
       
   927 
       
   928     /**
       
   929      * <p>Adds a listener to a registered MBean.</p>
       
   930      *
       
   931      * <p>The default implementation of this method first calls
       
   932      * {@link #getDynamicMBeanFor getDynamicMBeanFor(listenerName)}.
       
   933      * If that successfully returns an object, call it {@code
       
   934      * mbean}, then (a) if {@code mbean} is an instance of {@link
       
   935      * NotificationListener} then this method calls {@link
       
   936      * #addNotificationListener(ObjectName, NotificationListener,
       
   937      * NotificationFilter, Object) addNotificationListener(name, mbean, filter,
       
   938      * handback)}, otherwise (b) this method throws an exception as specified
       
   939      * for this case.</p>
       
   940      *
       
   941      * <p>This default implementation is not appropriate for Virtual MBeans,
       
   942      * although that only matters if the object returned by {@code
       
   943      * getDynamicMBeanFor} can be an instance of
       
   944      * {@code NotificationListener}.</p>
       
   945      *
       
   946      * @throws RuntimeOperationsException {@inheritDoc}
       
   947      */
       
   948     public void addNotificationListener(ObjectName name, ObjectName listenerName,
       
   949             NotificationFilter filter, Object handback)
       
   950             throws InstanceNotFoundException {
       
   951         NotificationListener listener = getListenerMBean(listenerName);
       
   952         addNotificationListener(name, listener, filter, handback);
       
   953     }
       
   954 
       
   955     /**
       
   956      * {@inheritDoc}
       
   957      *
       
   958      * <p>This operation is not supported in this base class implementation.
       
   959      * The default implementation of this method always throws
       
   960      * {@link RuntimeOperationsException} wrapping
       
   961      * {@link UnsupportedOperationException}.</p>
       
   962      *
       
   963      * @throws javax.management.RuntimeOperationsException wrapping
       
   964      *        {@link UnsupportedOperationException}
       
   965      */
       
   966     public void removeNotificationListener(ObjectName name,
       
   967             ObjectName listenerName)
       
   968             throws InstanceNotFoundException, ListenerNotFoundException {
       
   969         NotificationListener listener = getListenerMBean(listenerName);
       
   970         removeNotificationListener(name, listener);
       
   971     }
       
   972 
       
   973     /**
       
   974      * {@inheritDoc}
       
   975      *
       
   976      * <p>This operation is not supported in this base class implementation.
       
   977      * The default implementation of this method always throws
       
   978      * {@link RuntimeOperationsException} wrapping
       
   979      * {@link UnsupportedOperationException}.</p>
       
   980      *
       
   981      * @throws javax.management.RuntimeOperationsException wrapping
       
   982      *        {@link UnsupportedOperationException}
       
   983      */
       
   984     public void removeNotificationListener(ObjectName name,
       
   985             ObjectName listenerName, NotificationFilter filter,
       
   986             Object handback)
       
   987             throws InstanceNotFoundException, ListenerNotFoundException {
       
   988         NotificationListener listener = getListenerMBean(listenerName);
       
   989         removeNotificationListener(name, listener, filter, handback);
       
   990     }
       
   991 
       
   992     private NotificationListener getListenerMBean(ObjectName listenerName)
       
   993             throws InstanceNotFoundException {
       
   994         Object mbean = getDynamicMBeanFor(listenerName);
       
   995         if (mbean instanceof NotificationListener)
       
   996             return (NotificationListener) mbean;
       
   997         else {
       
   998             throw newIllegalArgumentException(
       
   999                     "MBean is not a NotificationListener: " + listenerName);
       
  1000         }
       
  1001     }
       
  1002 
       
  1003 
       
  1004     /**
       
  1005      * {@inheritDoc}
       
  1006      *
       
  1007      * <p>This operation is not supported in this base class implementation.
       
  1008      * The default implementation of this method always throws
       
  1009      * {@link InstanceNotFoundException} wrapping
       
  1010      * {@link UnsupportedOperationException}.</p>
       
  1011      *
       
  1012      * @return the default implementation of this method never returns.
       
  1013      * @throws javax.management.RuntimeOperationsException wrapping
       
  1014      *        {@link UnsupportedOperationException}
       
  1015      */
       
  1016     public ClassLoader getClassLoader(ObjectName loaderName)
       
  1017             throws InstanceNotFoundException {
       
  1018         final UnsupportedOperationException failed =
       
  1019                 new UnsupportedOperationException("getClassLoader");
       
  1020         final InstanceNotFoundException x =
       
  1021                 new InstanceNotFoundException(String.valueOf(loaderName));
       
  1022         x.initCause(failed);
       
  1023         throw x;
       
  1024     }
       
  1025 
       
  1026     /**
       
  1027      * {@inheritDoc}
       
  1028      *
       
  1029      * <p>The default implementation of this method calls
       
  1030      * {@link #getDynamicMBeanFor getDynamicMBeanFor(mbeanName)} and applies
       
  1031      * the logic just described to the result.</p>
       
  1032      */
       
  1033     public ClassLoader getClassLoaderFor(ObjectName mbeanName)
       
  1034             throws InstanceNotFoundException {
       
  1035         final DynamicMBean mbean = nonNullMBeanFor(mbeanName);
       
  1036         if (mbean instanceof DynamicWrapperMBean)
       
  1037             return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
       
  1038         else
       
  1039             return mbean.getClass().getClassLoader();
       
  1040     }
       
  1041 
       
  1042     /**
       
  1043      * {@inheritDoc}
       
  1044      *
       
  1045      * <p>The default implementation of this method returns a
       
  1046      * {@link ClassLoaderRepository} containing exactly one loader,
       
  1047      * the {@linkplain Thread#getContextClassLoader() context class loader}
       
  1048      * for the current thread.
       
  1049      * Subclasses can override this method to return a different
       
  1050      * {@code ClassLoaderRepository}.</p>
       
  1051      */
       
  1052     public ClassLoaderRepository getClassLoaderRepository() {
       
  1053         // We return a new ClassLoaderRepository each time this
       
  1054         // method is called. This is by design, because the
       
  1055         // SingletonClassLoaderRepository is a very small object and
       
  1056         // getClassLoaderRepository() will not be called very often
       
  1057         // (the connector server calls it once) - in the context of
       
  1058         // MBeanServerSupport there's a very good chance that this method will
       
  1059         // *never* be called.
       
  1060         ClassLoader ccl = Thread.currentThread().getContextClassLoader();
       
  1061         return Util.getSingleClassLoaderRepository(ccl);
       
  1062     }
       
  1063 
       
  1064 
       
  1065     /**
       
  1066      * {@inheritDoc}
       
  1067      *
       
  1068      * <p>This operation is not supported in this base class implementation.
       
  1069      * The default implementation of this method always throws
       
  1070      * {@link RuntimeOperationsException} wrapping
       
  1071      * {@link UnsupportedOperationException}.</p>
       
  1072      * @throws javax.management.RuntimeOperationsException wrapping
       
  1073      *        {@link UnsupportedOperationException}
       
  1074      */
       
  1075     public ObjectInstance registerMBean(Object object, ObjectName name)
       
  1076             throws InstanceAlreadyExistsException, MBeanRegistrationException,
       
  1077             NotCompliantMBeanException {
       
  1078         throw newUnsupportedException("registerMBean");
       
  1079     }
       
  1080 
       
  1081     /**
       
  1082      * {@inheritDoc}
       
  1083      *
       
  1084      * <p>This operation is not supported in this base class implementation.
       
  1085      * The default implementation of this method always throws
       
  1086      * {@link RuntimeOperationsException} wrapping
       
  1087      * {@link UnsupportedOperationException}.
       
  1088      * @throws javax.management.RuntimeOperationsException wrapping
       
  1089      *        {@link UnsupportedOperationException}
       
  1090      */
       
  1091     public void unregisterMBean(ObjectName name)
       
  1092             throws InstanceNotFoundException, MBeanRegistrationException {
       
  1093         throw newUnsupportedException("unregisterMBean");
       
  1094     }
       
  1095 
       
  1096     /**
       
  1097      * Calls {@link #createMBean(String, ObjectName,
       
  1098      *           ObjectName, Object[], String[], boolean)
       
  1099      * createMBean(className, name, null, params, signature, true)};
       
  1100      */
       
  1101     public final ObjectInstance createMBean(String className, ObjectName name,
       
  1102             Object[] params, String[] signature)
       
  1103             throws ReflectionException, InstanceAlreadyExistsException,
       
  1104             MBeanRegistrationException, MBeanException,
       
  1105             NotCompliantMBeanException {
       
  1106         try {
       
  1107             return safeCreateMBean(className, name, null, params, signature, true);
       
  1108         } catch (InstanceNotFoundException ex) {
       
  1109             // should not happen!
       
  1110             throw new MBeanException(ex, "Unexpected exception: " + ex);
       
  1111         }
       
  1112     }
       
  1113 
       
  1114     /**
       
  1115      * Calls {@link #createMBean(String, ObjectName,
       
  1116      *           ObjectName, Object[], String[], boolean)
       
  1117      * createMBean(className,name, loaderName, params, signature, false)};
       
  1118      */
       
  1119     public final ObjectInstance createMBean(String className, ObjectName name,
       
  1120             ObjectName loaderName, Object[] params, String[] signature)
       
  1121             throws ReflectionException, InstanceAlreadyExistsException,
       
  1122             MBeanRegistrationException, MBeanException,
       
  1123             NotCompliantMBeanException, InstanceNotFoundException {
       
  1124         return safeCreateMBean(className, name, loaderName, params, signature, false);
       
  1125     }
       
  1126 
       
  1127     /**
       
  1128      * Calls {@link #createMBean(String, ObjectName,
       
  1129      *           ObjectName, Object[], String[], boolean)
       
  1130      * createMBean(className, name, null, null, null, true)};
       
  1131      */
       
  1132     public final ObjectInstance createMBean(String className, ObjectName name)
       
  1133         throws ReflectionException, InstanceAlreadyExistsException,
       
  1134             MBeanRegistrationException, MBeanException,
       
  1135             NotCompliantMBeanException {
       
  1136         try {
       
  1137             return safeCreateMBean(className, name, null, null, null, true);
       
  1138         } catch (InstanceNotFoundException ex) {
       
  1139             // should not happen!
       
  1140             throw new MBeanException(ex, "Unexpected exception: " + ex);
       
  1141         }
       
  1142     }
       
  1143 
       
  1144     /**
       
  1145      * Calls {@link #createMBean(String, ObjectName,
       
  1146      *           ObjectName, Object[], String[], boolean)
       
  1147      * createMBean(className, name, loaderName, null, null, false)};
       
  1148      */
       
  1149     public final ObjectInstance createMBean(String className, ObjectName name,
       
  1150             ObjectName loaderName)
       
  1151             throws ReflectionException, InstanceAlreadyExistsException,
       
  1152             MBeanRegistrationException, MBeanException,
       
  1153             NotCompliantMBeanException, InstanceNotFoundException {
       
  1154         return safeCreateMBean(className, name, loaderName, null, null, false);
       
  1155     }
       
  1156 
       
  1157     // make sure all exceptions are correctly wrapped in a JMXException
       
  1158     private ObjectInstance safeCreateMBean(String className,
       
  1159             ObjectName name, ObjectName loaderName, Object[] params,
       
  1160             String[] signature, boolean useRepository)
       
  1161             throws ReflectionException, InstanceAlreadyExistsException,
       
  1162             MBeanRegistrationException, MBeanException,
       
  1163             NotCompliantMBeanException, InstanceNotFoundException {
       
  1164         try {
       
  1165             return createMBean(className, name, loaderName, params,
       
  1166                                signature, useRepository);
       
  1167         } catch (ReflectionException x) { throw x;
       
  1168         } catch (InstanceAlreadyExistsException x) { throw x;
       
  1169         } catch (MBeanRegistrationException x) { throw x;
       
  1170         } catch (MBeanException x) { throw x;
       
  1171         } catch (NotCompliantMBeanException x) { throw x;
       
  1172         } catch (InstanceNotFoundException x) { throw x;
       
  1173         } catch (SecurityException x) { throw x;
       
  1174         } catch (JMRuntimeException x) { throw x;
       
  1175         } catch (RuntimeException x) {
       
  1176             throw new RuntimeOperationsException(x, x.toString());
       
  1177         } catch (Exception x) {
       
  1178             throw new MBeanException(x, x.toString());
       
  1179         }
       
  1180     }
       
  1181 
       
  1182 
       
  1183     /**
       
  1184      * {@inheritDoc}
       
  1185      *
       
  1186      * <p>This operation is not supported in this base class implementation.
       
  1187      * The default implementation of this method always throws
       
  1188      * {@link RuntimeOperationsException} wrapping
       
  1189      * {@link UnsupportedOperationException}.</p>
       
  1190      *
       
  1191      * @throws javax.management.RuntimeOperationsException wrapping
       
  1192      *        {@link UnsupportedOperationException}
       
  1193      */
       
  1194     public Object instantiate(String className)
       
  1195             throws ReflectionException, MBeanException {
       
  1196         throw new UnsupportedOperationException("Not applicable.");
       
  1197     }
       
  1198 
       
  1199     /**
       
  1200      * {@inheritDoc}
       
  1201      *
       
  1202      * <p>This operation is not supported in this base class implementation.
       
  1203      * The default implementation of this method always throws
       
  1204      * {@link RuntimeOperationsException} wrapping
       
  1205      * {@link UnsupportedOperationException}.</p>
       
  1206      *
       
  1207      * @throws javax.management.RuntimeOperationsException wrapping
       
  1208      *        {@link UnsupportedOperationException}
       
  1209      */
       
  1210     public Object instantiate(String className, ObjectName loaderName)
       
  1211             throws ReflectionException, MBeanException,
       
  1212             InstanceNotFoundException {
       
  1213         throw new UnsupportedOperationException("Not applicable.");
       
  1214     }
       
  1215 
       
  1216     /**
       
  1217      * {@inheritDoc}
       
  1218      *
       
  1219      * <p>This operation is not supported in this base class implementation.
       
  1220      * The default implementation of this method always throws
       
  1221      * {@link RuntimeOperationsException} wrapping
       
  1222      * {@link UnsupportedOperationException}.</p>
       
  1223      *
       
  1224      * @throws javax.management.RuntimeOperationsException wrapping
       
  1225      *        {@link UnsupportedOperationException}
       
  1226      */
       
  1227     public Object instantiate(String className, Object[] params,
       
  1228             String[] signature) throws ReflectionException, MBeanException {
       
  1229         throw new UnsupportedOperationException("Not applicable.");
       
  1230     }
       
  1231 
       
  1232     /**
       
  1233      * {@inheritDoc}
       
  1234      *
       
  1235      * <p>This operation is not supported in this base class implementation.
       
  1236      * The default implementation of this method always throws
       
  1237      * {@link RuntimeOperationsException} wrapping
       
  1238      * {@link UnsupportedOperationException}.</p>
       
  1239      *
       
  1240      * @throws javax.management.RuntimeOperationsException wrapping
       
  1241      *        {@link UnsupportedOperationException}
       
  1242      */
       
  1243     public Object instantiate(String className, ObjectName loaderName,
       
  1244             Object[] params, String[] signature)
       
  1245             throws ReflectionException, MBeanException,
       
  1246             InstanceNotFoundException {
       
  1247         throw new UnsupportedOperationException("Not applicable.");
       
  1248     }
       
  1249 
       
  1250 
       
  1251     /**
       
  1252      * {@inheritDoc}
       
  1253      *
       
  1254      * <p>This operation is not supported in this base class implementation.
       
  1255      * The default implementation of this method always throws
       
  1256      * {@link RuntimeOperationsException} wrapping
       
  1257      * {@link UnsupportedOperationException}.</p>
       
  1258      *
       
  1259      * @throws javax.management.RuntimeOperationsException wrapping
       
  1260      *        {@link UnsupportedOperationException}
       
  1261      */
       
  1262     @Deprecated
       
  1263     public ObjectInputStream deserialize(ObjectName name, byte[] data)
       
  1264             throws InstanceNotFoundException, OperationsException {
       
  1265         throw new UnsupportedOperationException("Not applicable.");
       
  1266     }
       
  1267 
       
  1268     /**
       
  1269      * {@inheritDoc}
       
  1270      *
       
  1271      * <p>This operation is not supported in this base class implementation.
       
  1272      * The default implementation of this method always throws
       
  1273      * {@link RuntimeOperationsException} wrapping
       
  1274      * {@link UnsupportedOperationException}.</p>
       
  1275      *
       
  1276      * @throws javax.management.RuntimeOperationsException wrapping
       
  1277      *        {@link UnsupportedOperationException}
       
  1278      */
       
  1279     @Deprecated
       
  1280     public ObjectInputStream deserialize(String className, byte[] data)
       
  1281             throws OperationsException, ReflectionException {
       
  1282         throw new UnsupportedOperationException("Not applicable.");
       
  1283     }
       
  1284 
       
  1285     /**
       
  1286      * {@inheritDoc}
       
  1287      *
       
  1288      * <p>This operation is not supported in this base class implementation.
       
  1289      * The default implementation of this method always throws
       
  1290      * {@link RuntimeOperationsException} wrapping
       
  1291      * {@link UnsupportedOperationException}.</p>
       
  1292      *
       
  1293      * @throws javax.management.RuntimeOperationsException wrapping
       
  1294      *        {@link UnsupportedOperationException}
       
  1295      */
       
  1296     @Deprecated
       
  1297     public ObjectInputStream deserialize(String className,
       
  1298             ObjectName loaderName, byte[] data)
       
  1299             throws InstanceNotFoundException, OperationsException,
       
  1300             ReflectionException {
       
  1301         throw new UnsupportedOperationException("Not applicable.");
       
  1302     }
       
  1303 
       
  1304 
       
  1305     // Calls getDynamicMBeanFor, and throws an InstanceNotFoundException
       
  1306     // if the returned mbean is null.
       
  1307     // The DynamicMBean returned by this method is thus guaranteed to be
       
  1308     // non null.
       
  1309     //
       
  1310     private DynamicMBean nonNullMBeanFor(ObjectName name)
       
  1311             throws InstanceNotFoundException {
       
  1312         if (name == null)
       
  1313             throw newIllegalArgumentException("Null ObjectName");
       
  1314         if (name.getDomain().equals("")) {
       
  1315             String defaultDomain = getDefaultDomain();
       
  1316             try {
       
  1317                 // XXX change to ObjectName.switchDomain
       
  1318                 // current code DOES NOT PRESERVE the order of keys
       
  1319                 name = new ObjectName(defaultDomain, name.getKeyPropertyList());
       
  1320             } catch (Exception e) {
       
  1321                 throw newIllegalArgumentException(
       
  1322                         "Illegal default domain: " + defaultDomain);
       
  1323             }
       
  1324         }
       
  1325         final DynamicMBean mbean = getDynamicMBeanFor(name);
       
  1326         if (mbean!=null) return mbean;
       
  1327         throw new InstanceNotFoundException(String.valueOf(name));
       
  1328     }
       
  1329 
       
  1330     static RuntimeException newUnsupportedException(String operation) {
       
  1331         return new RuntimeOperationsException(
       
  1332             new UnsupportedOperationException(
       
  1333                 operation+": Not supported in this namespace"));
       
  1334     }
       
  1335 
       
  1336     static RuntimeException newIllegalArgumentException(String msg) {
       
  1337         return new RuntimeOperationsException(
       
  1338                 new IllegalArgumentException(msg));
       
  1339     }
       
  1340 
       
  1341 }