/* * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.jmx.interceptor; // JMX RI import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; import com.sun.jmx.mbeanserver.DynamicMBean2; import com.sun.jmx.mbeanserver.Introspector; import com.sun.jmx.mbeanserver.MBeanInstantiator; import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository; import com.sun.jmx.mbeanserver.NamedObject; import com.sun.jmx.mbeanserver.Repository; import com.sun.jmx.mbeanserver.Repository.RegistrationContext; import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.util.EnvHelp; import java.io.ObjectInputStream; import java.lang.ref.WeakReference; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.WeakHashMap; import java.util.logging.Level; // JMX import import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; 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.MBeanPermission; import javax.management.MBeanRegistration; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MBeanServerDelegate; import javax.management.MBeanServerNotification; import javax.management.MBeanTrustPermission; import javax.management.NotCompliantMBeanException; import javax.management.Notification; 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.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; import javax.management.loading.ClassLoaderRepository; /** * This is the default class for MBean manipulation on the agent side. It * contains the methods necessary for the creation, registration, and * deletion of MBeans as well as the access methods for registered MBeans. * This is the core component of the JMX infrastructure. *
* Every MBean which is added to the MBean server becomes manageable: its attributes and operations * become remotely accessible through the connectors/adaptors connected to that MBean server. * A Java object cannot be registered in the MBean server unless it is a JMX compliant MBean. *
* When an MBean is registered or unregistered in the MBean server an
* {@link javax.management.MBeanServerNotification MBeanServerNotification}
* Notification is emitted. To register an object as listener to MBeanServerNotifications
* you should call the MBean server method {@link #addNotificationListener addNotificationListener} with Do not forget to call
* This method does not performed any kind of test compliance,
* and the caller should make sure that the given
* This methods performed all the basic steps needed for object
* registration:
* Return the {@link java.lang.ClassLoader} that was used for
* loading the class of the named MBean.
* @param mbeanName The ObjectName of the MBean.
* @return The ClassLoader used for that MBean.
* @exception InstanceNotFoundException if the named MBean is not found.
*/
public ClassLoader getClassLoaderFor(ObjectName mbeanName)
throws InstanceNotFoundException {
DynamicMBean instance = getMBean(mbeanName);
checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor");
return getResource(instance).getClass().getClassLoader();
}
/**
* Return the named {@link java.lang.ClassLoader}.
* @param loaderName The ObjectName of the ClassLoader.
* @return The named ClassLoader.
* @exception InstanceNotFoundException if the named ClassLoader
* is not found.
*/
public ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
if (loaderName == null) {
checkMBeanPermission((String) null, null, null, "getClassLoader");
return server.getClass().getClassLoader();
}
DynamicMBean instance = getMBean(loaderName);
checkMBeanPermission(instance, null, loaderName, "getClassLoader");
Object resource = getResource(instance);
/* Check if the given MBean is a ClassLoader */
if (!(resource instanceof ClassLoader))
throw new InstanceNotFoundException(loaderName.toString() +
" is not a classloader");
return (ClassLoader) resource;
}
/**
* Sends an MBeanServerNotifications with the specified type for the
* MBean with the specified ObjectName
*/
private void sendNotification(String NotifType, ObjectName name) {
// ------------------------------
// ------------------------------
// ---------------------
// Create notification
// ---------------------
MBeanServerNotification notif = new MBeanServerNotification(
NotifType,MBeanServerDelegate.DELEGATE_NAME,0,name);
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"sendNotification", NotifType + " " + name);
}
delegate.sendNotification(notif);
}
/**
* Applies the specified queries to the set of NamedObjects.
*/
private SetObjectName
* the ObjectName
of the {@link javax.management.MBeanServerDelegate MBeanServerDelegate}.
* This ObjectName
is:
*
* JMImplementation:type=MBeanServerDelegate
.
*
* @since 1.5
*/
public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
/** The MBeanInstantiator object used by the
* DefaultMBeanServerInterceptor */
private final transient MBeanInstantiator instantiator;
/** The MBean server object that is associated to the
* DefaultMBeanServerInterceptor */
private transient MBeanServer server = null;
/** The MBean server delegate object that is associated to the
* DefaultMBeanServerInterceptor */
private final transient MBeanServerDelegate delegate;
/** The Repository object used by the DefaultMBeanServerInterceptor */
private final transient Repository repository;
/** Wrappers for client listeners. */
/* See the comment before addNotificationListener below. */
private final transient
WeakHashMapinitialize(outer,delegate)
* before using this object.
* @param outer A pointer to the MBeanServer object that must be
* passed to the MBeans when invoking their
* {@link javax.management.MBeanRegistration} interface.
* @param delegate A pointer to the MBeanServerDelegate associated
* with the new MBeanServer. The new MBeanServer must register
* this MBean in its MBean repository.
* @param instantiator The MBeanInstantiator that will be used to
* instantiate MBeans and take care of class loading issues.
* @param repository The repository to use for this MBeanServer.
*/
public DefaultMBeanServerInterceptor(MBeanServer outer,
MBeanServerDelegate delegate,
MBeanInstantiator instantiator,
Repository repository) {
if (outer == null) throw new
IllegalArgumentException("outer MBeanServer cannot be null");
if (delegate == null) throw new
IllegalArgumentException("MBeanServerDelegate cannot be null");
if (instantiator == null) throw new
IllegalArgumentException("MBeanInstantiator cannot be null");
if (repository == null) throw new
IllegalArgumentException("Repository cannot be null");
this.server = outer;
this.delegate = delegate;
this.instantiator = instantiator;
this.repository = repository;
this.domain = repository.getDefaultDomain();
}
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
return createMBean(className, name, (Object[]) null, (String[]) null);
}
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
return createMBean(className, name, loaderName, (Object[]) null,
(String[]) null);
}
public ObjectInstance createMBean(String className, ObjectName name,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
return createMBean(className, name, null, true,
params, signature);
} catch (InstanceNotFoundException e) {
/* Can only happen if loaderName doesn't exist, but we just
passed null, so we shouldn't get this exception. */
throw EnvHelp.initCause(
new IllegalArgumentException("Unexpected exception: " + e), e);
}
}
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
return createMBean(className, name, loaderName, false,
params, signature);
}
private ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName,
boolean withDefaultLoaderRepository,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
Class> theClass;
if (className == null) {
final RuntimeException wrapped =
new IllegalArgumentException("The class name cannot be null");
throw new RuntimeOperationsException(wrapped,
"Exception occurred during MBean creation");
}
if (name != null) {
if (name.isPattern()) {
final RuntimeException wrapped =
new IllegalArgumentException("Invalid name->" +
name.toString());
final String msg = "Exception occurred during MBean creation";
throw new RuntimeOperationsException(wrapped, msg);
}
name = nonDefaultDomain(name);
}
checkMBeanPermission(className, null, null, "instantiate");
checkMBeanPermission(className, null, name, "registerMBean");
/* Load the appropriate class. */
if (withDefaultLoaderRepository) {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"createMBean",
"ClassName = " + className + ", ObjectName = " + name);
}
theClass =
instantiator.findClassWithDefaultLoaderRepository(className);
} else if (loaderName == null) {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"createMBean", "ClassName = " + className +
", ObjectName = " + name + ", Loader name = null");
}
theClass = instantiator.findClass(className,
server.getClass().getClassLoader());
} else {
loaderName = nonDefaultDomain(loaderName);
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"createMBean", "ClassName = " + className +
", ObjectName = " + name +
", Loader name = " + loaderName);
}
theClass = instantiator.findClass(className, loaderName);
}
checkMBeanTrustPermission(theClass);
// Check that the MBean can be instantiated by the MBeanServer.
Introspector.testCreation(theClass);
// Check the JMX MBean compliance of the class
Introspector.checkCompliance(theClass);
Object moi= instantiator.instantiate(theClass, params, signature,
server.getClass().getClassLoader());
final String infoClassName = getNewMBeanClassName(moi);
return registerObject(infoClassName, moi, name);
}
public ObjectInstance registerMBean(Object object, ObjectName name)
throws InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException {
// ------------------------------
// ------------------------------
Class> theClass = object.getClass();
Introspector.checkCompliance(theClass);
final String infoClassName = getNewMBeanClassName(object);
checkMBeanPermission(infoClassName, null, name, "registerMBean");
checkMBeanTrustPermission(theClass);
return registerObject(infoClassName, object, name);
}
private static String getNewMBeanClassName(Object mbeanToRegister)
throws NotCompliantMBeanException {
if (mbeanToRegister instanceof DynamicMBean) {
DynamicMBean mbean = (DynamicMBean) mbeanToRegister;
final String name;
try {
name = mbean.getMBeanInfo().getClassName();
} catch (Exception e) {
// Includes case where getMBeanInfo() returns null
NotCompliantMBeanException ncmbe =
new NotCompliantMBeanException("Bad getMBeanInfo()");
ncmbe.initCause(e);
throw ncmbe;
}
if (name == null) {
final String msg = "MBeanInfo has null class name";
throw new NotCompliantMBeanException(msg);
}
return name;
} else
return mbeanToRegister.getClass().getName();
}
private final Setobject
in the repository, with the
* given name
.
* This method is called by the various createMBean() flavours
* and by registerMBean() after all MBean compliance tests
* have been performed.
* object
* is MBean compliant.
*
*
* @param object A reference to a MBean compliant object.
* @param name The ObjectName of the object
implements the MBeanRegistration
* interface, it invokes preRegister() on the object.name
.object
implements the
* MBeanRegistration interface, it invokes postRegister()
* on the object.object
MBean.
* @return the actual ObjectName with which the object was registered.
* @exception InstanceAlreadyExistsException if an object is already
* registered with that name.
* @exception MBeanRegistrationException if an exception occurs during
* registration.
**/
private ObjectInstance registerObject(String classname,
Object object, ObjectName name)
throws InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException {
if (object == null) {
final RuntimeException wrapped =
new IllegalArgumentException("Cannot add null object");
throw new RuntimeOperationsException(wrapped,
"Exception occurred trying to register the MBean");
}
DynamicMBean mbean = Introspector.makeDynamicMBean(object);
return registerDynamicMBean(classname, mbean, name);
}
private ObjectInstance registerDynamicMBean(String classname,
DynamicMBean mbean,
ObjectName name)
throws InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException {
name = nonDefaultDomain(name);
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"registerMBean", "ObjectName = " + name);
}
ObjectName logicalName = preRegister(mbean, server, name);
// preRegister returned successfully, so from this point on we
// must call postRegister(false) if there is any problem.
boolean registered = false;
boolean registerFailed = false;
ResourceContext context = null;
try {
if (mbean instanceof DynamicMBean2) {
try {
((DynamicMBean2) mbean).preRegister2(server, logicalName);
registerFailed = true; // until we succeed
} catch (Exception e) {
if (e instanceof RuntimeException)
throw (RuntimeException) e;
if (e instanceof InstanceAlreadyExistsException)
throw (InstanceAlreadyExistsException) e;
throw new RuntimeException(e);
}
}
if (logicalName != name && logicalName != null) {
logicalName =
ObjectName.getInstance(nonDefaultDomain(logicalName));
}
checkMBeanPermission(classname, null, logicalName, "registerMBean");
if (logicalName == null) {
final RuntimeException wrapped =
new IllegalArgumentException("No object name specified");
throw new RuntimeOperationsException(wrapped,
"Exception occurred trying to register the MBean");
}
final Object resource = getResource(mbean);
// Register the MBean with the repository.
// Returns the resource context that was used.
// The returned context does nothing for regular MBeans.
// For ClassLoader MBeans the context makes it possible to register these
// objects with the appropriate framework artifacts, such as
// the CLR, from within the repository lock.
// In case of success, we also need to call context.done() at the
// end of this method.
//
context = registerWithRepository(resource, mbean, logicalName);
registerFailed = false;
registered = true;
} finally {
try {
postRegister(logicalName, mbean, registered, registerFailed);
} finally {
if (registered && context!=null) context.done();
}
}
return new ObjectInstance(logicalName, classname);
}
private static void throwMBeanRegistrationException(Throwable t, String where)
throws MBeanRegistrationException {
if (t instanceof RuntimeException) {
throw new RuntimeMBeanException((RuntimeException)t,
"RuntimeException thrown " + where);
} else if (t instanceof Error) {
throw new RuntimeErrorException((Error)t,
"Error thrown " + where);
} else if (t instanceof MBeanRegistrationException) {
throw (MBeanRegistrationException)t;
} else if (t instanceof Exception) {
throw new MBeanRegistrationException((Exception)t,
"Exception thrown " + where);
} else // neither Error nor Exception??
throw new RuntimeException(t);
}
private static ObjectName preRegister(
DynamicMBean mbean, MBeanServer mbs, ObjectName name)
throws InstanceAlreadyExistsException, MBeanRegistrationException {
ObjectName newName = null;
try {
if (mbean instanceof MBeanRegistration)
newName = ((MBeanRegistration) mbean).preRegister(mbs, name);
} catch (Throwable t) {
throwMBeanRegistrationException(t, "in preRegister method");
}
if (newName != null) return newName;
else return name;
}
private static void postRegister(
ObjectName logicalName, DynamicMBean mbean,
boolean registrationDone, boolean registerFailed) {
if (registerFailed && mbean instanceof DynamicMBean2)
((DynamicMBean2) mbean).registerFailed();
try {
if (mbean instanceof MBeanRegistration)
((MBeanRegistration) mbean).postRegister(registrationDone);
} catch (RuntimeException e) {
MBEANSERVER_LOGGER.fine("While registering MBean ["+logicalName+
"]: " + "Exception thrown by postRegister: " +
"rethrowing <"+e+">, but keeping the MBean registered");
throw new RuntimeMBeanException(e,
"RuntimeException thrown in postRegister method: "+
"rethrowing <"+e+">, but keeping the MBean registered");
} catch (Error er) {
MBEANSERVER_LOGGER.fine("While registering MBean ["+logicalName+
"]: " + "Error thrown by postRegister: " +
"rethrowing <"+er+">, but keeping the MBean registered");
throw new RuntimeErrorException(er,
"Error thrown in postRegister method: "+
"rethrowing <"+er+">, but keeping the MBean registered");
}
}
private static void preDeregisterInvoke(MBeanRegistration moi)
throws MBeanRegistrationException {
try {
moi.preDeregister();
} catch (Throwable t) {
throwMBeanRegistrationException(t, "in preDeregister method");
}
}
private static void postDeregisterInvoke(ObjectName mbean,
MBeanRegistration moi) {
try {
moi.postDeregister();
} catch (RuntimeException e) {
MBEANSERVER_LOGGER.fine("While unregistering MBean ["+mbean+
"]: " + "Exception thrown by postDeregister: " +
"rethrowing <"+e+">, although the MBean is succesfully " +
"unregistered");
throw new RuntimeMBeanException(e,
"RuntimeException thrown in postDeregister method: "+
"rethrowing <"+e+
">, although the MBean is sucessfully unregistered");
} catch (Error er) {
MBEANSERVER_LOGGER.fine("While unregistering MBean ["+mbean+
"]: " + "Error thrown by postDeregister: " +
"rethrowing <"+er+">, although the MBean is succesfully " +
"unregistered");
throw new RuntimeErrorException(er,
"Error thrown in postDeregister method: "+
"rethrowing <"+er+
">, although the MBean is sucessfully unregistered");
}
}
/**
* Gets a specific MBean controlled by the DefaultMBeanServerInterceptor.
* The name must have a non-default domain.
*/
private DynamicMBean getMBean(ObjectName name)
throws InstanceNotFoundException {
if (name == null) {
throw new RuntimeOperationsException(new
IllegalArgumentException("Object name cannot be null"),
"Exception occurred trying to get an MBean");
}
DynamicMBean obj = repository.retrieve(name);
if (obj == null) {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"getMBean", name + " : Found no object");
}
throw new InstanceNotFoundException(name.toString());
}
return obj;
}
private static Object getResource(DynamicMBean mbean) {
if (mbean instanceof DynamicMBean2)
return ((DynamicMBean2) mbean).getResource();
else
return mbean;
}
private ObjectName nonDefaultDomain(ObjectName name) {
if (name == null || name.getDomain().length() > 0)
return name;
/* The ObjectName looks like ":a=b", and that's what its
toString() will return in this implementation. So
we can just stick the default domain in front of it
to get a non-default-domain name. We depend on the
fact that toString() works like that and that it
leaves wildcards in place (so we can detect an error
if one is supplied where it shouldn't be). */
final String completeName = domain + name;
return Util.newObjectName(completeName);
}
public String getDefaultDomain() {
return domain;
}
/*
* Notification handling.
*
* This is not trivial, because the MBeanServer translates the
* source of a received notification from a reference to an MBean
* into the ObjectName of that MBean. While that does make
* notification sending easier for MBean writers, it comes at a
* considerable cost. We need to replace the source of a
* notification, which is basically wrong if there are also
* listeners registered directly with the MBean (without going
* through the MBean server). We also need to wrap the listener
* supplied by the client of the MBeanServer with a listener that
* performs the substitution before forwarding. This is why we
* strongly discourage people from putting MBean references in the
* source of their notifications. Instead they should arrange to
* put the ObjectName there themselves.
*
* However, existing code relies on the substitution, so we are
* stuck with it.
*
* Here's how we handle it. When you add a listener, we make a
* ListenerWrapper around it. We look that up in the
* listenerWrappers map, and if there was already a wrapper for
* that listener with the given ObjectName, we reuse it. This map
* is a WeakHashMap, so a listener that is no longer registered
* with any MBean can be garbage collected.
*
* We cannot use simpler solutions such as always creating a new
* wrapper or always registering the same listener with the MBean
* and using the handback to find the client's original listener.
* The reason is that we need to support the removeListener
* variant that removes all (listener,filter,handback) triples on
* a broadcaster that have a given listener. And we do not have
* any way to inspect a broadcaster's internal list of triples.
* So the same client listener must always map to the same
* listener registered with the broadcaster.
*
* Another possible solution would be to map from ObjectName to
* list of listener wrappers (or IdentityHashMap of listener
* wrappers), making this list the first time a listener is added
* on a given MBean, and removing it when the MBean is removed.
* This is probably more costly in memory, but could be useful if
* some day we don't want to rely on weak references.
*/
public void addNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
// ------------------------------
// ------------------------------
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"addNotificationListener", "ObjectName = " + name);
}
DynamicMBean instance = getMBean(name);
checkMBeanPermission(instance, null, name, "addNotificationListener");
NotificationBroadcaster broadcaster =
getNotificationBroadcaster(name, instance,
NotificationBroadcaster.class);
// ------------------
// Check listener
// ------------------
if (listener == null) {
throw new RuntimeOperationsException(new
IllegalArgumentException("Null listener"),"Null listener");
}
NotificationListener listenerWrapper =
getListenerWrapper(listener, name, instance, true);
broadcaster.addNotificationListener(listenerWrapper, filter, handback);
}
public void addNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
// ------------------------------
// ------------------------------
// ----------------
// Get listener object
// ----------------
DynamicMBean instance = getMBean(listener);
Object resource = getResource(instance);
if (!(resource instanceof NotificationListener)) {
throw new RuntimeOperationsException(new
IllegalArgumentException(listener.getCanonicalName()),
"The MBean " + listener.getCanonicalName() +
"does not implement the NotificationListener interface") ;
}
// ----------------
// Add a listener on an MBean
// ----------------
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"addNotificationListener",
"ObjectName = " + name + ", Listener = " + listener);
}
server.addNotificationListener(name,(NotificationListener) resource,
filter, handback) ;
}
public void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
removeNotificationListener(name, listener, null, null, true);
}
public void removeNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
removeNotificationListener(name, listener, filter, handback, false);
}
public void removeNotificationListener(ObjectName name,
ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
NotificationListener instance = getListener(listener);
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"removeNotificationListener",
"ObjectName = " + name + ", Listener = " + listener);
}
server.removeNotificationListener(name, instance);
}
public void removeNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
NotificationListener instance = getListener(listener);
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"removeNotificationListener",
"ObjectName = " + name + ", Listener = " + listener);
}
server.removeNotificationListener(name, instance, filter, handback);
}
private NotificationListener getListener(ObjectName listener)
throws ListenerNotFoundException {
// ----------------
// Get listener object
// ----------------
DynamicMBean instance;
try {
instance = getMBean(listener);
} catch (InstanceNotFoundException e) {
throw EnvHelp.initCause(
new ListenerNotFoundException(e.getMessage()), e);
}
Object resource = getResource(instance);
if (!(resource instanceof NotificationListener)) {
final RuntimeException exc =
new IllegalArgumentException(listener.getCanonicalName());
final String msg =
"MBean " + listener.getCanonicalName() + " does not " +
"implement " + NotificationListener.class.getName();
throw new RuntimeOperationsException(exc, msg);
}
return (NotificationListener) resource;
}
private void removeNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback,
boolean removeAll)
throws InstanceNotFoundException, ListenerNotFoundException {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"removeNotificationListener", "ObjectName = " + name);
}
DynamicMBean instance = getMBean(name);
checkMBeanPermission(instance, null, name, "removeNotificationListener");
/* We could simplify the code by assigning broadcaster after
assigning listenerWrapper, but that would change the error
behavior when both the broadcaster and the listener are
erroneous. */
Class extends NotificationBroadcaster> reqClass =
removeAll ? NotificationBroadcaster.class : NotificationEmitter.class;
NotificationBroadcaster broadcaster =
getNotificationBroadcaster(name, instance, reqClass);
NotificationListener listenerWrapper =
getListenerWrapper(listener, name, instance, false);
if (listenerWrapper == null)
throw new ListenerNotFoundException("Unknown listener");
if (removeAll)
broadcaster.removeNotificationListener(listenerWrapper);
else {
NotificationEmitter emitter = (NotificationEmitter) broadcaster;
emitter.removeNotificationListener(listenerWrapper,
filter,
handback);
}
}
private static