| /* |
| * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| package javax.management.namespace; |
| |
| import com.sun.jmx.defaults.JmxProperties; |
| import com.sun.jmx.mbeanserver.Util; |
| import java.io.ObjectInputStream; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.management.Attribute; |
| import javax.management.AttributeList; |
| import javax.management.AttributeNotFoundException; |
| import javax.management.DynamicMBean; |
| import javax.management.DynamicWrapperMBean; |
| import javax.management.InstanceAlreadyExistsException; |
| import javax.management.InstanceNotFoundException; |
| import javax.management.IntrospectionException; |
| import javax.management.InvalidAttributeValueException; |
| import javax.management.JMRuntimeException; |
| import javax.management.ListenerNotFoundException; |
| import javax.management.MBeanException; |
| import javax.management.MBeanInfo; |
| import javax.management.MBeanRegistrationException; |
| import javax.management.MBeanServer; |
| import javax.management.NotCompliantMBeanException; |
| import javax.management.NotificationBroadcaster; |
| import javax.management.NotificationEmitter; |
| import javax.management.NotificationFilter; |
| import javax.management.NotificationListener; |
| import javax.management.ObjectInstance; |
| import javax.management.ObjectName; |
| import javax.management.OperationsException; |
| import javax.management.QueryEval; |
| import javax.management.QueryExp; |
| import javax.management.ReflectionException; |
| import javax.management.RuntimeOperationsException; |
| import javax.management.loading.ClassLoaderRepository; |
| |
| /** |
| * <p>Base class for custom implementations of the {@link MBeanServer} |
| * interface. The commonest use of this class is as the {@linkplain |
| * JMXNamespace#getSourceServer() source server} for a {@link |
| * JMXNamespace}, although this class can be used anywhere an {@code |
| * MBeanServer} instance is required. Note that the usual ways to |
| * obtain an {@code MBeanServer} instance are either to use {@link |
| * java.lang.management.ManagementFactory#getPlatformMBeanServer() |
| * ManagementFactory.getPlatformMBeanServer()} or to use the {@code |
| * newMBeanServer} or {@code createMBeanServer} methods from {@link |
| * javax.management.MBeanServerFactory MBeanServerFactory}. {@code |
| * MBeanServerSupport} is for certain cases where those are not |
| * appropriate.</p> |
| * |
| * <p>There are two main use cases for this class: <a |
| * href="#special-purpose">special-purpose MBeanServer implementations</a>, |
| * and <a href="#virtual">namespaces containing Virtual MBeans</a>. The next |
| * sections explain these use cases.</p> |
| * |
| * <p>In the simplest case, a subclass needs to implement only two methods:</p> |
| * |
| * <ul> |
| * <li> |
| * {@link #getNames getNames} which returns the name of |
| * all MBeans handled by this {@code MBeanServer}. |
| * </li> |
| * <li> |
| * {@link #getDynamicMBeanFor getDynamicMBeanFor} which returns a |
| * {@link DynamicMBean} that can be used to invoke operations and |
| * obtain meta data (MBeanInfo) on a given MBean. |
| * </li> |
| * </ul> |
| * |
| * <p>Subclasses can create such {@link DynamicMBean} MBeans on the fly - for |
| * instance, using the class {@link javax.management.StandardMBean}, just for |
| * the duration of an MBeanServer method call.</p> |
| * |
| * <h4 id="special-purpose">Special-purpose MBeanServer implementations</h4> |
| * |
| * <p>In some cases |
| * the general-purpose {@code MBeanServer} that you get from |
| * {@link javax.management.MBeanServerFactory MBeanServerFactory} is not |
| * appropriate. You might need different security checks, or you might |
| * want a mock {@code MBeanServer} suitable for use in tests, or you might |
| * want a simplified and optimized {@code MBeanServer} for a special purpose.</p> |
| * |
| * <p>As an example of a special-purpose {@code MBeanServer}, the class {@link |
| * javax.management.QueryNotificationFilter QueryNotificationFilter} constructs |
| * an {@code MBeanServer} instance every time it filters a notification, |
| * with just one MBean that represents the notification. Although it could |
| * use {@code MBeanServerFactory.newMBeanServer}, a special-purpose {@code |
| * MBeanServer} will be quicker to create, use less memory, and have simpler |
| * methods that execute faster.</p> |
| * |
| * <p>Here is an example of a special-purpose {@code MBeanServer} |
| * implementation that contains exactly one MBean, which is specified at the |
| * time of creation.</p> |
| * |
| * <pre> |
| * public class SingletonMBeanServer extends MBeanServerSupport { |
| * private final ObjectName objectName; |
| * private final DynamicMBean mbean; |
| * |
| * public SingletonMBeanServer(ObjectName objectName, DynamicMBean mbean) { |
| * this.objectName = objectName; |
| * this.mbean = mbean; |
| * } |
| * |
| * @Override |
| * protected {@code Set<ObjectName>} {@link #getNames getNames}() { |
| * return Collections.singleton(objectName); |
| * } |
| * |
| * @Override |
| * public DynamicMBean {@link #getDynamicMBeanFor |
| * getDynamicMBeanFor}(ObjectName name) |
| * throws InstanceNotFoundException { |
| * if (objectName.equals(name)) |
| * return mbean; |
| * else |
| * throw new InstanceNotFoundException(name); |
| * } |
| * } |
| * </pre> |
| * |
| * <p>Using this class, you could make an {@code MBeanServer} that contains |
| * a {@link javax.management.timer.Timer Timer} MBean like this:</p> |
| * |
| * <pre> |
| * Timer timer = new Timer(); |
| * DynamicMBean mbean = new {@link javax.management.StandardMBean |
| * StandardMBean}(timer, TimerMBean.class); |
| * ObjectName name = new ObjectName("com.example:type=Timer"); |
| * MBeanServer timerMBS = new SingletonMBeanServer(name, mbean); |
| * </pre> |
| * |
| * <p>When {@code getDynamicMBeanFor} always returns the same object for the |
| * same name, as here, notifications work in the expected way: if the object |
| * is a {@link NotificationEmitter} then listeners can be added using |
| * {@link MBeanServer#addNotificationListener(ObjectName, NotificationListener, |
| * NotificationFilter, Object) MBeanServer.addNotificationListener}. If |
| * {@code getDynamicMBeanFor} does not always return the same object for the |
| * same name, more work is needed to make notifications work, as described |
| * <a href="#notifs">below</a>.</p> |
| * |
| * <h4 id="virtual">Namespaces containing Virtual MBeans</h4> |
| * |
| * <p>Virtual MBeans are MBeans that do not exist as Java objects, |
| * except transiently while they are being accessed. This is useful when |
| * there might be very many of them, or when keeping track of their creation |
| * and deletion might be expensive or hard. For example, you might have one |
| * MBean per system process. With an ordinary {@code MBeanServer}, you would |
| * have to list the system processes in order to create an MBean object for |
| * each one, and you would have to track the arrival and departure of system |
| * processes in order to create or delete the corresponding MBeans. With |
| * Virtual MBeans, you only need the MBean for a given process at the exact |
| * point where it is referenced with a call such as |
| * {@link MBeanServer#getAttribute MBeanServer.getAttribute}.</p> |
| * |
| * <p>Here is an example of an {@code MBeanServer} implementation that has |
| * one MBean for every system property. The system property {@code "java.home"} |
| * is represented by the MBean called {@code |
| * com.example:type=Property,name="java.home"}, with an attribute called |
| * {@code Value} that is the value of the property.</p> |
| * |
| * <pre> |
| * public interface PropertyMBean { |
| * public String getValue(); |
| * } |
| * |
| * <a name="PropsMBS"></a>public class PropsMBS extends MBeanServerSupport { |
| * private static ObjectName newObjectName(String name) { |
| * try { |
| * return new ObjectName(name); |
| * } catch (MalformedObjectNameException e) { |
| * throw new AssertionError(e); |
| * } |
| * } |
| * |
| * public static class PropertyImpl implements PropertyMBean { |
| * private final String name; |
| * |
| * public PropertyImpl(String name) { |
| * this.name = name; |
| * } |
| * |
| * public String getValue() { |
| * return System.getProperty(name); |
| * } |
| * } |
| * |
| * @Override |
| * public DynamicMBean {@link #getDynamicMBeanFor |
| * getDynamicMBeanFor}(ObjectName name) |
| * throws InstanceNotFoundException { |
| * |
| * // Check that the name is a legal one for a Property MBean |
| * ObjectName namePattern = newObjectName( |
| * "com.example:type=Property,name=\"*\""); |
| * if (!namePattern.apply(name)) |
| * throw new InstanceNotFoundException(name); |
| * |
| * // Extract the name of the property that the MBean corresponds to |
| * String propName = ObjectName.unquote(name.getKeyProperty("name")); |
| * if (System.getProperty(propName) == null) |
| * throw new InstanceNotFoundException(name); |
| * |
| * // Construct and return a transient MBean object |
| * PropertyMBean propMBean = new PropertyImpl(propName); |
| * return new StandardMBean(propMBean, PropertyMBean.class, false); |
| * } |
| * |
| * @Override |
| * protected {@code Set<ObjectName>} {@link #getNames getNames}() { |
| * {@code Set<ObjectName> names = new TreeSet<ObjectName>();} |
| * Properties props = System.getProperties(); |
| * for (String propName : props.stringPropertyNames()) { |
| * ObjectName objectName = newObjectName( |
| * "com.example:type=Property,name=" + |
| * ObjectName.quote(propName)); |
| * names.add(objectName); |
| * } |
| * return names; |
| * } |
| * } |
| * </pre> |
| * |
| * <p id="virtual-notif-example">Because the {@code getDynamicMBeanFor} method |
| * returns a different object every time it is called, the default handling |
| * of notifications will not work, as explained <a href="#notifs">below</a>. |
| * In this case it does not matter, because the object returned by {@code |
| * getDynamicMBeanFor} is not a {@code NotificationEmitter}, so {@link |
| * MBeanServer#addNotificationListener(ObjectName, NotificationListener, |
| * NotificationFilter, Object) MBeanServer.addNotificationListener} will |
| * always fail. But if we wanted to extend {@code PropsMBS} so that the MBean |
| * for property {@code "foo"} emitted a notification every time that property |
| * changed, we would need to do it as shown below. (Because there is no API to |
| * be informed when a property changes, this code assumes that some other code |
| * calls the {@code propertyChanged} method every time a property changes.)</p> |
| * |
| * <pre> |
| * public class PropsMBS { |
| * ...as <a href="#PropsMBS">above</a>... |
| * |
| * private final {@link VirtualEventManager} vem = new VirtualEventManager(); |
| * |
| * @Override |
| * public NotificationEmitter {@link #getNotificationEmitterFor |
| * getNotificationEmitterFor}( |
| * ObjectName name) throws InstanceNotFoundException { |
| * getDynamicMBeanFor(name); // check that the name is valid |
| * return vem.{@link VirtualEventManager#getNotificationEmitterFor |
| * getNotificationEmitterFor}(name); |
| * } |
| * |
| * public void propertyChanged(String name, String newValue) { |
| * ObjectName objectName = newObjectName( |
| * "com.example:type=Property,name=" + ObjectName.quote(name)); |
| * Notification n = new Notification( |
| * "com.example.property.changed", objectName, 0L, |
| * "Property " + name + " changed"); |
| * n.setUserData(newValue); |
| * vem.{@link VirtualEventManager#publish publish}(objectName, n); |
| * } |
| * } |
| * </pre> |
| * |
| * <h4 id="creation">MBean creation and deletion</h4> |
| * |
| * <p>MBean creation through {@code MBeanServer.createMBean} is disabled |
| * by default. Subclasses which need to support MBean creation |
| * through {@code createMBean} need to implement a single method {@link |
| * #createMBean(String, ObjectName, ObjectName, Object[], String[], |
| * boolean)}.</p> |
| * |
| * <p>Similarly MBean registration and unregistration through {@code |
| * registerMBean} and {@code unregisterMBean} are disabled by default. |
| * Subclasses which need to support MBean registration and |
| * unregistration will need to implement {@link #registerMBean registerMBean} |
| * and {@link #unregisterMBean unregisterMBean}.</p> |
| * |
| * <h4 id="notifs">Notifications</h4> |
| * |
| * <p>By default {@link MBeanServer#addNotificationListener(ObjectName, |
| * NotificationListener, NotificationFilter, Object) addNotificationListener} |
| * is accepted for an MBean <em>{@code name}</em> if {@link #getDynamicMBeanFor |
| * getDynamicMBeanFor}<code>(<em>name</em>)</code> returns an object that is a |
| * {@link NotificationEmitter}. That is appropriate if |
| * {@code getDynamicMBeanFor}<code>(<em>name</em>)</code> always returns the |
| * same object for the same <em>{@code name}</em>. But with |
| * Virtual MBeans, every call to {@code getDynamicMBeanFor} returns a new object, |
| * which is discarded as soon as the MBean request has finished. |
| * So a listener added to that object would be immediately forgotten.</p> |
| * |
| * <p>The simplest way for a subclass that defines Virtual MBeans |
| * to support notifications is to create a private {@link VirtualEventManager} |
| * and override the method {@link |
| * #getNotificationEmitterFor getNotificationEmitterFor} as follows:</p> |
| * |
| * <pre> |
| * private final VirtualEventManager vem = new VirtualEventManager(); |
| * |
| * @Override |
| * public NotificationEmitter getNotificationEmitterFor( |
| * ObjectName name) throws InstanceNotFoundException { |
| * // Check that the name is a valid Virtual MBean. |
| * // This is the easiest way to do that, but not always the |
| * // most efficient: |
| * getDynamicMBeanFor(name); |
| * |
| * // Return an object that supports add/removeNotificationListener |
| * // through the VirtualEventManager. |
| * return vem.getNotificationEmitterFor(name); |
| * } |
| * </pre> |
| * |
| * <p>A notification <em>{@code n}</em> can then be sent from the Virtual MBean |
| * called <em>{@code name}</em> by calling {@link VirtualEventManager#publish |
| * vem.publish}<code>(<em>name</em>, <em>n</em>)</code>. See the example |
| * <a href="#virtual-notif-example">above</a>.</p> |
| * |
| * @since 1.7 |
| */ |
| public abstract class MBeanServerSupport implements MBeanServer { |
| |
| /** |
| * A logger for this class. |
| */ |
| private static final Logger LOG = |
| JmxProperties.NAMESPACE_LOGGER; |
| |
| /** |
| * <p>Make a new {@code MBeanServerSupport} instance.</p> |
| */ |
| protected MBeanServerSupport() { |
| } |
| |
| /** |
| * <p>Returns a dynamically created handle that makes it possible to |
| * access the named MBean for the duration of a method call.</p> |
| * |
| * <p>An easy way to create such a {@link DynamicMBean} handle is, for |
| * instance, to create a temporary MXBean instance and to wrap it in |
| * an instance of |
| * {@link javax.management.StandardMBean}. |
| * This handle should remain valid for the duration of the call |
| * but can then be discarded.</p> |
| * @param name the name of the MBean for which a request was received. |
| * @return a {@link DynamicMBean} handle that can be used to invoke |
| * operations on the named MBean. |
| * @throws InstanceNotFoundException if no such MBean is supposed |
| * to exist. |
| */ |
| public abstract DynamicMBean getDynamicMBeanFor(ObjectName name) |
| throws InstanceNotFoundException; |
| |
| /** |
| * <p>Subclasses should implement this method to return |
| * the names of all MBeans handled by this object instance.</p> |
| * |
| * <p>The object returned by getNames() should be safely {@linkplain |
| * Set#iterator iterable} even in the presence of other threads that may |
| * cause the set of names to change. Typically this means one of the |
| * following:</p> |
| * |
| * <ul> |
| * <li>the returned set of names is always the same; or |
| * <li>the returned set of names is an object such as a {@link |
| * java.util.concurrent.CopyOnWriteArraySet CopyOnWriteArraySet} that is |
| * safely iterable even if the set is changed by other threads; or |
| * <li>a new Set is constructed every time this method is called. |
| * </ul> |
| * |
| * @return the names of all MBeans handled by this object. |
| */ |
| protected abstract Set<ObjectName> getNames(); |
| |
| /** |
| * <p>List names matching the given pattern. |
| * The default implementation of this method calls {@link #getNames()} |
| * and returns the subset of those names matching {@code pattern}.</p> |
| * |
| * @param pattern an ObjectName pattern |
| * @return the list of MBean names that match the given pattern. |
| */ |
| protected Set<ObjectName> getMatchingNames(ObjectName pattern) { |
| return Util.filterMatchingNames(pattern, getNames()); |
| } |
| |
| /** |
| * <p>Returns a {@link NotificationEmitter} which can be used to |
| * subscribe or unsubscribe for notifications with the named |
| * mbean.</p> |
| * |
| * <p>The default implementation of this method calls {@link |
| * #getDynamicMBeanFor getDynamicMBeanFor(name)} and returns that object |
| * if it is a {@code NotificationEmitter}, otherwise null. See <a |
| * href="#notifs">above</a> for further discussion of notification |
| * handling.</p> |
| * |
| * @param name The name of the MBean whose notifications are being |
| * subscribed, or unsuscribed. |
| * |
| * @return A {@link NotificationEmitter} that can be used to subscribe or |
| * unsubscribe for notifications emitted by the named MBean, or {@code |
| * null} if the MBean does not emit notifications and should not be |
| * considered as a {@code NotificationEmitter}. |
| * |
| * @throws InstanceNotFoundException if {@code name} is not the name of |
| * an MBean in this {@code MBeanServer}. |
| */ |
| public NotificationEmitter getNotificationEmitterFor(ObjectName name) |
| throws InstanceNotFoundException { |
| DynamicMBean mbean = getDynamicMBeanFor(name); |
| if (mbean instanceof NotificationEmitter) |
| return (NotificationEmitter) mbean; |
| else |
| return null; |
| } |
| |
| private NotificationEmitter getNonNullNotificationEmitterFor( |
| ObjectName name) |
| throws InstanceNotFoundException { |
| NotificationEmitter emitter = getNotificationEmitterFor(name); |
| if (emitter == null) { |
| IllegalArgumentException iae = new IllegalArgumentException( |
| "Not a NotificationEmitter: " + name); |
| throw new RuntimeOperationsException(iae); |
| } |
| return emitter; |
| } |
| |
| /** |
| * <p>Creates a new MBean in the MBean name space. |
| * This operation is not supported in this base class implementation.</p> |
| * The default implementation of this method always throws an {@link |
| * UnsupportedOperationException} |
| * wrapped in a {@link RuntimeOperationsException}.</p> |
| * |
| * <p>Subclasses may redefine this method to provide an implementation. |
| * All the various flavors of {@code MBeanServer.createMBean} methods |
| * will eventually call this method. A subclass that wishes to |
| * support MBean creation through {@code createMBean} thus only |
| * needs to provide an implementation for this one method. |
| * |
| * @param className The class name of the MBean to be instantiated. |
| * @param name The object name of the MBean. May be null. |
| * @param params An array containing the parameters of the |
| * constructor to be invoked. |
| * @param signature An array containing the signature of the |
| * constructor to be invoked. |
| * @param loaderName The object name of the class loader to be used. |
| * @param useCLR This parameter is {@code true} when this method |
| * is called from one of the {@code MBeanServer.createMBean} methods |
| * whose signature does not include the {@code ObjectName} of an |
| * MBean class loader to use for loading the MBean class. |
| * |
| * @return An <CODE>ObjectInstance</CODE>, containing the |
| * <CODE>ObjectName</CODE> and the Java class name of the newly |
| * instantiated MBean. If the contained <code>ObjectName</code> |
| * is <code>n</code>, the contained Java class name is |
| * <code>{@link javax.management.MBeanServer#getMBeanInfo |
| * getMBeanInfo(n)}.getClassName()</code>. |
| * |
| * @exception ReflectionException Wraps a |
| * <CODE>java.lang.ClassNotFoundException</CODE> or a |
| * <CODE>java.lang.Exception</CODE> that occurred when trying to |
| * invoke the MBean's constructor. |
| * @exception InstanceAlreadyExistsException The MBean is already |
| * under the control of the MBean server. |
| * @exception MBeanRegistrationException The |
| * <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE> |
| * interface) method of the MBean has thrown an exception. The |
| * MBean will not be registered. |
| * @exception MBeanException The constructor of the MBean has |
| * thrown an exception |
| * @exception NotCompliantMBeanException This class is not a JMX |
| * compliant MBean |
| * @exception InstanceNotFoundException The specified class loader |
| * is not registered in the MBean server. |
| * @exception RuntimeOperationsException Wraps either: |
| * <ul> |
| * <li>a <CODE>java.lang.IllegalArgumentException</CODE>: The className |
| * passed in parameter is null, the <CODE>ObjectName</CODE> passed in |
| * parameter contains a pattern or no <CODE>ObjectName</CODE> is specified |
| * for the MBean; or</li> |
| * <li>an {@code UnsupportedOperationException} if creating MBeans is not |
| * supported by this {@code MBeanServer} implementation. |
| * </ul> |
| */ |
| public ObjectInstance createMBean(String className, |
| ObjectName name, ObjectName loaderName, Object[] params, |
| String[] signature, boolean useCLR) |
| throws ReflectionException, InstanceAlreadyExistsException, |
| MBeanRegistrationException, MBeanException, |
| NotCompliantMBeanException, InstanceNotFoundException { |
| throw newUnsupportedException("createMBean"); |
| } |
| |
| |
| /** |
| * <p>Attempts to determine whether the named MBean should be |
| * considered as an instance of a given class. The default implementation |
| * of this method calls {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} |
| * to get an MBean object. Then its behaviour is the same as the standard |
| * {@link MBeanServer#isInstanceOf MBeanServer.isInstanceOf} method.</p> |
| * |
| * {@inheritDoc} |
| */ |
| public boolean isInstanceOf(ObjectName name, String className) |
| throws InstanceNotFoundException { |
| |
| final DynamicMBean instance = nonNullMBeanFor(name); |
| |
| try { |
| final String mbeanClassName = instance.getMBeanInfo().getClassName(); |
| |
| if (mbeanClassName.equals(className)) |
| return true; |
| |
| final Object resource; |
| final ClassLoader cl; |
| if (instance instanceof DynamicWrapperMBean) { |
| DynamicWrapperMBean d = (DynamicWrapperMBean) instance; |
| resource = d.getWrappedObject(); |
| cl = d.getWrappedClassLoader(); |
| } else { |
| resource = instance; |
| cl = instance.getClass().getClassLoader(); |
| } |
| |
| final Class<?> classNameClass = Class.forName(className, false, cl); |
| |
| if (classNameClass.isInstance(resource)) |
| return true; |
| |
| if (classNameClass == NotificationBroadcaster.class || |
| classNameClass == NotificationEmitter.class) { |
| try { |
| getNotificationEmitterFor(name); |
| return true; |
| } catch (Exception x) { |
| LOG.finest("MBean " + name + |
| " is not a notification emitter. Ignoring: "+x); |
| return false; |
| } |
| } |
| |
| final Class<?> resourceClass = Class.forName(mbeanClassName, false, cl); |
| return classNameClass.isAssignableFrom(resourceClass); |
| } catch (Exception x) { |
| /* Could be SecurityException or ClassNotFoundException */ |
| LOG.logp(Level.FINEST, |
| MBeanServerSupport.class.getName(), |
| "isInstanceOf", "Exception calling isInstanceOf", x); |
| return false; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method returns the string |
| * "DefaultDomain".</p> |
| */ |
| public String getDefaultDomain() { |
| return "DefaultDomain"; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method returns |
| * {@link #getNames()}.size().</p> |
| */ |
| public Integer getMBeanCount() { |
| return getNames().size(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method first calls {@link #getNames |
| * getNames()} to get a list of all MBean names, |
| * and from this set of names, derives the set of domains which contain |
| * MBeans.</p> |
| */ |
| public String[] getDomains() { |
| final Set<ObjectName> names = getNames(); |
| final Set<String> res = new TreeSet<String>(); |
| for (ObjectName n : names) { |
| if (n == null) continue; // not allowed but you never know. |
| res.add(n.getDomain()); |
| } |
| return res.toArray(new String[res.size()]); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link |
| * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle |
| * to the named MBean, |
| * and then call {@link DynamicMBean#getAttribute getAttribute} |
| * on that {@link DynamicMBean} handle.</p> |
| * |
| * @throws RuntimeOperationsException {@inheritDoc} |
| */ |
| public Object getAttribute(ObjectName name, String attribute) |
| throws MBeanException, AttributeNotFoundException, |
| InstanceNotFoundException, ReflectionException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| return mbean.getAttribute(attribute); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} |
| * to obtain a handle to the named MBean, |
| * and then call {@link DynamicMBean#setAttribute setAttribute} |
| * on that {@link DynamicMBean} handle.</p> |
| * |
| * @throws RuntimeOperationsException {@inheritDoc} |
| */ |
| public void setAttribute(ObjectName name, Attribute attribute) |
| throws InstanceNotFoundException, AttributeNotFoundException, |
| InvalidAttributeValueException, MBeanException, |
| ReflectionException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| mbean.setAttribute(attribute); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a |
| * handle to the named MBean, |
| * and then call {@link DynamicMBean#getAttributes getAttributes} |
| * on that {@link DynamicMBean} handle.</p> |
| * |
| * @throws RuntimeOperationsException {@inheritDoc} |
| */ |
| public AttributeList getAttributes(ObjectName name, |
| String[] attributes) throws InstanceNotFoundException, |
| ReflectionException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| return mbean.getAttributes(attributes); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a |
| * handle to the named MBean, |
| * and then call {@link DynamicMBean#setAttributes setAttributes} |
| * on that {@link DynamicMBean} handle.</p> |
| * |
| * @throws RuntimeOperationsException {@inheritDoc} |
| */ |
| public AttributeList setAttributes(ObjectName name, AttributeList attributes) |
| throws InstanceNotFoundException, ReflectionException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| return mbean.setAttributes(attributes); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a |
| * handle to the named MBean, |
| * and then call {@link DynamicMBean#invoke invoke} |
| * on that {@link DynamicMBean} handle.</p> |
| */ |
| public Object invoke(ObjectName name, String operationName, |
| Object[] params, String[] signature) |
| throws InstanceNotFoundException, MBeanException, |
| ReflectionException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| return mbean.invoke(operationName, params, signature); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a |
| * handle to the named MBean, |
| * and then call {@link DynamicMBean#getMBeanInfo getMBeanInfo} |
| * on that {@link DynamicMBean} handle.</p> |
| */ |
| public MBeanInfo getMBeanInfo(ObjectName name) |
| throws InstanceNotFoundException, IntrospectionException, |
| ReflectionException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| return mbean.getMBeanInfo(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will call |
| * {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}.<!-- |
| * -->{@link DynamicMBean#getMBeanInfo getMBeanInfo()}.<!-- |
| * -->{@link MBeanInfo#getClassName getClassName()} to get the |
| * class name to combine with {@code name} to produce a new |
| * {@code ObjectInstance}.</p> |
| */ |
| public ObjectInstance getObjectInstance(ObjectName name) |
| throws InstanceNotFoundException { |
| final DynamicMBean mbean = nonNullMBeanFor(name); |
| final String className = mbean.getMBeanInfo().getClassName(); |
| return new ObjectInstance(name, className); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first call {@link |
| * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle to the |
| * named MBean. If {@code getDynamicMBeanFor} returns an object, {@code |
| * isRegistered} will return true. If {@code getDynamicMBeanFor} returns |
| * null or throws {@link InstanceNotFoundException}, {@code isRegistered} |
| * will return false.</p> |
| * |
| * @throws RuntimeOperationsException {@inheritDoc} |
| */ |
| public boolean isRegistered(ObjectName name) { |
| try { |
| final DynamicMBean mbean = getDynamicMBeanFor(name); |
| return mbean!=null; |
| } catch (InstanceNotFoundException x) { |
| if (LOG.isLoggable(Level.FINEST)) |
| LOG.finest("MBean "+name+" is not registered: "+x); |
| return false; |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method will first |
| * call {@link #queryNames queryNames} |
| * to get a list of all matching MBeans, and then, for each returned name, |
| * call {@link #getObjectInstance getObjectInstance(name)}.</p> |
| */ |
| public Set<ObjectInstance> queryMBeans(ObjectName pattern, QueryExp query) { |
| final Set<ObjectName> names = queryNames(pattern, query); |
| if (names.isEmpty()) return Collections.emptySet(); |
| final Set<ObjectInstance> mbeans = new HashSet<ObjectInstance>(); |
| for (ObjectName name : names) { |
| try { |
| mbeans.add(getObjectInstance(name)); |
| } catch (SecurityException x) { // DLS: OK |
| continue; |
| } catch (InstanceNotFoundException x) { // DLS: OK |
| continue; |
| } |
| } |
| return mbeans; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method calls {@link #getMatchingNames |
| * getMatchingNames(pattern)} to obtain a list of MBeans matching |
| * the given name pattern. If the {@code query} parameter is null, |
| * this will be the result. Otherwise, it will evaluate the |
| * {@code query} parameter for each of the returned names, exactly |
| * as an {@code MBeanServer} would. This might result in |
| * {@link #getDynamicMBeanFor getDynamicMBeanFor} being called |
| * several times for each returned name.</p> |
| */ |
| public Set<ObjectName> queryNames(ObjectName pattern, QueryExp query) { |
| try { |
| final Set<ObjectName> res = getMatchingNames(pattern); |
| return filterListOfObjectNames(res, query); |
| } catch (Exception x) { |
| LOG.fine("Unexpected exception raised in queryNames: "+x); |
| LOG.log(Level.FINEST, "Unexpected exception raised in queryNames", x); |
| } |
| // We reach here only when an exception was raised. |
| // |
| return Collections.emptySet(); |
| } |
| |
| private final static boolean apply(final QueryExp query, |
| final ObjectName on, |
| final MBeanServer srv) { |
| boolean res = false; |
| MBeanServer oldServer = QueryEval.getMBeanServer(); |
| query.setMBeanServer(srv); |
| try { |
| res = query.apply(on); |
| } catch (Exception e) { |
| LOG.finest("QueryExp.apply threw exception, returning false." + |
| " Cause: "+e); |
| res = false; |
| } finally { |
| /* |
| * query.setMBeanServer is probably |
| * QueryEval.setMBeanServer so put back the old |
| * value. Since that method uses a ThreadLocal |
| * variable, this code is only needed for the |
| * unusual case where the user creates a custom |
| * QueryExp that calls a nested query on another |
| * MBeanServer. |
| */ |
| query.setMBeanServer(oldServer); |
| } |
| return res; |
| } |
| |
| /** |
| * Filters a {@code Set<ObjectName>} according to a pattern and a query. |
| * This might be quite inefficient for virtual name spaces. |
| */ |
| Set<ObjectName> |
| filterListOfObjectNames(Set<ObjectName> list, |
| QueryExp query) { |
| if (list.isEmpty() || query == null) |
| return list; |
| |
| // create a new result set |
| final Set<ObjectName> result = new HashSet<ObjectName>(); |
| |
| for (ObjectName on : list) { |
| // if on doesn't match query exclude it. |
| if (apply(query, on, this)) |
| result.add(on); |
| } |
| return result; |
| } |
| |
| |
| // Don't use {@inheritDoc}, because we don't want to say that the |
| // MBeanServer replaces a reference to the MBean by its ObjectName. |
| /** |
| * <p>Adds a listener to a registered MBean. A notification emitted by |
| * the MBean will be forwarded to the listener.</p> |
| * |
| * <p>This implementation calls |
| * {@link #getNotificationEmitterFor getNotificationEmitterFor} |
| * and invokes {@code addNotificationListener} on the |
| * {@link NotificationEmitter} it returns. |
| * |
| * @see #getDynamicMBeanFor getDynamicMBeanFor |
| * @see #getNotificationEmitterFor getNotificationEmitterFor |
| */ |
| public void addNotificationListener(ObjectName name, |
| NotificationListener listener, NotificationFilter filter, |
| Object handback) throws InstanceNotFoundException { |
| final NotificationEmitter emitter = |
| getNonNullNotificationEmitterFor(name); |
| emitter.addNotificationListener(listener, filter, handback); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This implementation calls |
| * {@link #getNotificationEmitterFor getNotificationEmitterFor} |
| * and invokes {@code removeNotificationListener} on the |
| * {@link NotificationEmitter} it returns. |
| * @see #getDynamicMBeanFor getDynamicMBeanFor |
| * @see #getNotificationEmitterFor getNotificationEmitterFor |
| */ |
| public void removeNotificationListener(ObjectName name, |
| NotificationListener listener) |
| throws InstanceNotFoundException, ListenerNotFoundException { |
| final NotificationEmitter emitter = |
| getNonNullNotificationEmitterFor(name); |
| emitter.removeNotificationListener(listener); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This implementation calls |
| * {@link #getNotificationEmitterFor getNotificationEmitterFor} |
| * and invokes {@code removeNotificationListener} on the |
| * {@link NotificationEmitter} it returns. |
| * @see #getDynamicMBeanFor getDynamicMBeanFor |
| * @see #getNotificationEmitterFor getNotificationEmitterFor |
| */ |
| public void removeNotificationListener(ObjectName name, |
| NotificationListener listener, NotificationFilter filter, |
| Object handback) |
| throws InstanceNotFoundException, ListenerNotFoundException { |
| NotificationEmitter emitter = |
| getNonNullNotificationEmitterFor(name); |
| emitter.removeNotificationListener(listener); |
| } |
| |
| |
| /** |
| * <p>Adds a listener to a registered MBean.</p> |
| * |
| * <p>The default implementation of this method first calls |
| * {@link #getDynamicMBeanFor getDynamicMBeanFor(listenerName)}. |
| * If that successfully returns an object, call it {@code |
| * mbean}, then (a) if {@code mbean} is an instance of {@link |
| * NotificationListener} then this method calls {@link |
| * #addNotificationListener(ObjectName, NotificationListener, |
| * NotificationFilter, Object) addNotificationListener(name, mbean, filter, |
| * handback)}, otherwise (b) this method throws an exception as specified |
| * for this case.</p> |
| * |
| * <p>This default implementation is not appropriate for Virtual MBeans, |
| * although that only matters if the object returned by {@code |
| * getDynamicMBeanFor} can be an instance of |
| * {@code NotificationListener}.</p> |
| * |
| * @throws RuntimeOperationsException {@inheritDoc} |
| */ |
| public void addNotificationListener(ObjectName name, ObjectName listenerName, |
| NotificationFilter filter, Object handback) |
| throws InstanceNotFoundException { |
| NotificationListener listener = getListenerMBean(listenerName); |
| addNotificationListener(name, listener, filter, handback); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public void removeNotificationListener(ObjectName name, |
| ObjectName listenerName) |
| throws InstanceNotFoundException, ListenerNotFoundException { |
| NotificationListener listener = getListenerMBean(listenerName); |
| removeNotificationListener(name, listener); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public void removeNotificationListener(ObjectName name, |
| ObjectName listenerName, NotificationFilter filter, |
| Object handback) |
| throws InstanceNotFoundException, ListenerNotFoundException { |
| NotificationListener listener = getListenerMBean(listenerName); |
| removeNotificationListener(name, listener, filter, handback); |
| } |
| |
| private NotificationListener getListenerMBean(ObjectName listenerName) |
| throws InstanceNotFoundException { |
| Object mbean = getDynamicMBeanFor(listenerName); |
| if (mbean instanceof NotificationListener) |
| return (NotificationListener) mbean; |
| else { |
| throw newIllegalArgumentException( |
| "MBean is not a NotificationListener: " + listenerName); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link InstanceNotFoundException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @return the default implementation of this method never returns. |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public ClassLoader getClassLoader(ObjectName loaderName) |
| throws InstanceNotFoundException { |
| final UnsupportedOperationException failed = |
| new UnsupportedOperationException("getClassLoader"); |
| final InstanceNotFoundException x = |
| new InstanceNotFoundException(String.valueOf(loaderName)); |
| x.initCause(failed); |
| throw x; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method calls |
| * {@link #getDynamicMBeanFor getDynamicMBeanFor(mbeanName)} and applies |
| * the logic just described to the result.</p> |
| */ |
| public ClassLoader getClassLoaderFor(ObjectName mbeanName) |
| throws InstanceNotFoundException { |
| final DynamicMBean mbean = nonNullMBeanFor(mbeanName); |
| if (mbean instanceof DynamicWrapperMBean) |
| return ((DynamicWrapperMBean) mbean).getWrappedClassLoader(); |
| else |
| return mbean.getClass().getClassLoader(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>The default implementation of this method returns a |
| * {@link ClassLoaderRepository} containing exactly one loader, |
| * the {@linkplain Thread#getContextClassLoader() context class loader} |
| * for the current thread. |
| * Subclasses can override this method to return a different |
| * {@code ClassLoaderRepository}.</p> |
| */ |
| public ClassLoaderRepository getClassLoaderRepository() { |
| // We return a new ClassLoaderRepository each time this |
| // method is called. This is by design, because the |
| // SingletonClassLoaderRepository is a very small object and |
| // getClassLoaderRepository() will not be called very often |
| // (the connector server calls it once) - in the context of |
| // MBeanServerSupport there's a very good chance that this method will |
| // *never* be called. |
| ClassLoader ccl = Thread.currentThread().getContextClassLoader(); |
| return Util.getSingleClassLoaderRepository(ccl); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public ObjectInstance registerMBean(Object object, ObjectName name) |
| throws InstanceAlreadyExistsException, MBeanRegistrationException, |
| NotCompliantMBeanException { |
| throw newUnsupportedException("registerMBean"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}. |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public void unregisterMBean(ObjectName name) |
| throws InstanceNotFoundException, MBeanRegistrationException { |
| throw newUnsupportedException("unregisterMBean"); |
| } |
| |
| /** |
| * Calls {@link #createMBean(String, ObjectName, |
| * ObjectName, Object[], String[], boolean) |
| * createMBean(className, name, null, params, signature, true)}; |
| */ |
| public final ObjectInstance createMBean(String className, ObjectName name, |
| Object[] params, String[] signature) |
| throws ReflectionException, InstanceAlreadyExistsException, |
| MBeanRegistrationException, MBeanException, |
| NotCompliantMBeanException { |
| try { |
| return safeCreateMBean(className, name, null, params, signature, true); |
| } catch (InstanceNotFoundException ex) { |
| // should not happen! |
| throw new MBeanException(ex, "Unexpected exception: " + ex); |
| } |
| } |
| |
| /** |
| * Calls {@link #createMBean(String, ObjectName, |
| * ObjectName, Object[], String[], boolean) |
| * createMBean(className,name, loaderName, params, signature, false)}; |
| */ |
| public final ObjectInstance createMBean(String className, ObjectName name, |
| ObjectName loaderName, Object[] params, String[] signature) |
| throws ReflectionException, InstanceAlreadyExistsException, |
| MBeanRegistrationException, MBeanException, |
| NotCompliantMBeanException, InstanceNotFoundException { |
| return safeCreateMBean(className, name, loaderName, params, signature, false); |
| } |
| |
| /** |
| * Calls {@link #createMBean(String, ObjectName, |
| * ObjectName, Object[], String[], boolean) |
| * createMBean(className, name, null, null, null, true)}; |
| */ |
| public final ObjectInstance createMBean(String className, ObjectName name) |
| throws ReflectionException, InstanceAlreadyExistsException, |
| MBeanRegistrationException, MBeanException, |
| NotCompliantMBeanException { |
| try { |
| return safeCreateMBean(className, name, null, null, null, true); |
| } catch (InstanceNotFoundException ex) { |
| // should not happen! |
| throw new MBeanException(ex, "Unexpected exception: " + ex); |
| } |
| } |
| |
| /** |
| * Calls {@link #createMBean(String, ObjectName, |
| * ObjectName, Object[], String[], boolean) |
| * createMBean(className, name, loaderName, null, null, false)}; |
| */ |
| public final ObjectInstance createMBean(String className, ObjectName name, |
| ObjectName loaderName) |
| throws ReflectionException, InstanceAlreadyExistsException, |
| MBeanRegistrationException, MBeanException, |
| NotCompliantMBeanException, InstanceNotFoundException { |
| return safeCreateMBean(className, name, loaderName, null, null, false); |
| } |
| |
| // make sure all exceptions are correctly wrapped in a JMXException |
| private ObjectInstance safeCreateMBean(String className, |
| ObjectName name, ObjectName loaderName, Object[] params, |
| String[] signature, boolean useRepository) |
| throws ReflectionException, InstanceAlreadyExistsException, |
| MBeanRegistrationException, MBeanException, |
| NotCompliantMBeanException, InstanceNotFoundException { |
| try { |
| return createMBean(className, name, loaderName, params, |
| signature, useRepository); |
| } catch (ReflectionException x) { throw x; |
| } catch (InstanceAlreadyExistsException x) { throw x; |
| } catch (MBeanRegistrationException x) { throw x; |
| } catch (MBeanException x) { throw x; |
| } catch (NotCompliantMBeanException x) { throw x; |
| } catch (InstanceNotFoundException x) { throw x; |
| } catch (SecurityException x) { throw x; |
| } catch (JMRuntimeException x) { throw x; |
| } catch (RuntimeException x) { |
| throw new RuntimeOperationsException(x, x.toString()); |
| } catch (Exception x) { |
| throw new MBeanException(x, x.toString()); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public Object instantiate(String className) |
| throws ReflectionException, MBeanException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public Object instantiate(String className, ObjectName loaderName) |
| throws ReflectionException, MBeanException, |
| InstanceNotFoundException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public Object instantiate(String className, Object[] params, |
| String[] signature) throws ReflectionException, MBeanException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| public Object instantiate(String className, ObjectName loaderName, |
| Object[] params, String[] signature) |
| throws ReflectionException, MBeanException, |
| InstanceNotFoundException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| @Deprecated |
| public ObjectInputStream deserialize(ObjectName name, byte[] data) |
| throws InstanceNotFoundException, OperationsException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| @Deprecated |
| public ObjectInputStream deserialize(String className, byte[] data) |
| throws OperationsException, ReflectionException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * <p>This operation is not supported in this base class implementation. |
| * The default implementation of this method always throws |
| * {@link RuntimeOperationsException} wrapping |
| * {@link UnsupportedOperationException}.</p> |
| * |
| * @throws javax.management.RuntimeOperationsException wrapping |
| * {@link UnsupportedOperationException} |
| */ |
| @Deprecated |
| public ObjectInputStream deserialize(String className, |
| ObjectName loaderName, byte[] data) |
| throws InstanceNotFoundException, OperationsException, |
| ReflectionException { |
| throw new UnsupportedOperationException("Not applicable."); |
| } |
| |
| |
| // Calls getDynamicMBeanFor, and throws an InstanceNotFoundException |
| // if the returned mbean is null. |
| // The DynamicMBean returned by this method is thus guaranteed to be |
| // non null. |
| // |
| private DynamicMBean nonNullMBeanFor(ObjectName name) |
| throws InstanceNotFoundException { |
| if (name == null) |
| throw newIllegalArgumentException("Null ObjectName"); |
| if (name.getDomain().equals("")) { |
| String defaultDomain = getDefaultDomain(); |
| try { |
| name = name.withDomain(getDefaultDomain()); |
| } catch (Exception e) { |
| throw newIllegalArgumentException( |
| "Illegal default domain: " + defaultDomain); |
| } |
| } |
| final DynamicMBean mbean = getDynamicMBeanFor(name); |
| if (mbean!=null) return mbean; |
| throw new InstanceNotFoundException(String.valueOf(name)); |
| } |
| |
| static RuntimeException newUnsupportedException(String operation) { |
| return new RuntimeOperationsException( |
| new UnsupportedOperationException( |
| operation+": Not supported in this namespace")); |
| } |
| |
| static RuntimeException newIllegalArgumentException(String msg) { |
| return new RuntimeOperationsException( |
| new IllegalArgumentException(msg)); |
| } |
| |
| } |