/* Server.java -- A GNU Classpath management server.
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.javax.management;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.io.StreamCorruptedException;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.BadAttributeValueExpException;
import javax.management.BadBinaryOpValueExpException;
import javax.management.BadStringOperationException;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidApplicationException;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MalformedObjectNameException;
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.QueryExp;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;
import javax.management.StandardMBean;

import javax.management.loading.ClassLoaderRepository;

/**
 * This class provides an {@link javax.management.MBeanServer}
 * implementation for GNU Classpath.
 *
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.5
 */
public class Server
  implements MBeanServer
{

  /**
   * The name of the delegate bean.
   */
  private static final ObjectName DELEGATE_NAME;

  /**
   * The registered beans, represented as a map of
   * {@link javax.management.ObjectName}s to
   * {@link gnu.javax.management.Server.ServerInfo}s.
   */
  private final ConcurrentHashMap<ObjectName,ServerInfo> beans =
    new ConcurrentHashMap<ObjectName,ServerInfo>();

  /**
   * The default domain.
   */
  private final String defaultDomain;

  /**
   * The outer server.
   */
  private final MBeanServer outer;

  /**
   * The class loader repository.
   */
  private ClassLoaderRepository repository;

  /**
   * The map of listener delegates to the true
   * listener.  We wrap this in an inner class
   * to delay initialisation until a listener
   * is actually added.
   */
  private static class LazyListenersHolder
  {
    private static final Map<NotificationListener,NotificationListener> listeners =
      new ConcurrentHashMap<NotificationListener,NotificationListener>();
  }

  /**
   * An MBean that emits notifications when an MBean is registered and
   * unregistered with this server.
   *
   */
  private final MBeanServerDelegate delegate;

  /**
   * Provides sequencing for notifications about registrations.
   */
  private static final AtomicLong sequenceNumber = new AtomicLong(1);

  /**
   * Initialise the delegate name.
   */
  static
  {
    try
      {
	DELEGATE_NAME = 
	  new ObjectName("JMImplementation:type=MBeanServerDelegate");
      }
    catch (MalformedObjectNameException e)
      {
	throw (Error) 
	  (new InternalError("Failed to construct " +
			     "the delegate's object name.").initCause(e));
      }
  }

  /**
   * Constructs a new management server using the specified
   * default domain, delegate bean and outer server.
   *
   * @param defaultDomain the default domain to use for beans constructed
   *               with no specified domain.
   * @param outer an {@link javax.management.MBeanServer} to pass
   *              to beans implementing the {@link MBeanRegistration}
   *              interface, or <code>null</code> if <code>this</code>
   *              should be passed.
   * @param delegate the delegate bean for this server.
   */
  public Server(String defaultDomain, MBeanServer outer,
		MBeanServerDelegate delegate)
  {
    this.defaultDomain = defaultDomain;
    this.outer = outer;
    this.delegate = delegate;
    try
      {
	registerMBean(delegate, DELEGATE_NAME);
      }
    catch (InstanceAlreadyExistsException e)
      {
	throw (Error) 
	  (new InternalError("The delegate bean is " +
			     "already registered.").initCause(e));
      }
    catch (MBeanRegistrationException e)
      {
	throw (Error) 
	  (new InternalError("The delegate bean's preRegister " +
			     "methods threw an exception.").initCause(e));
      }
    catch (NotCompliantMBeanException e)
      {
	throw (Error) 
	  (new InternalError("The delegate bean is " +
			     "not compliant.").initCause(e));
      }
  }

  /**
   * Checks for the necessary security privileges to perform an
   * operation.
   *
   * @param name the name of the bean being accessed.
   * @param member the name of the operation or attribute being
   *               accessed, or <code>null</code> if one is not
   *               involved.
   * @param action the action being performed.
   * @throws SecurityException if the action is denied.
   */
  private void checkSecurity(ObjectName name, String member,
			     String action)
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      try
	{
	  MBeanInfo info = null;
	  if (name != null)
	    {
	      Object bean = getBean(name);
	      Method method = bean.getClass().getMethod("getMBeanInfo");
	      info = (MBeanInfo) method.invoke(bean);
	    }
	  sm.checkPermission(new MBeanPermission((info == null) ? 
						 null : info.getClassName(),
						 member, name, action));
	}
      catch (InstanceNotFoundException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to get bean.").initCause(e));
	}
      catch (NoSuchMethodException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to get bean info.").initCause(e));
	}
      catch (IllegalAccessException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to get bean info.").initCause(e));
	}
      catch (IllegalArgumentException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to get bean info.").initCause(e));
	}
      catch (InvocationTargetException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to get bean info.").initCause(e));
	}
  }

  /**
   * Retrieves the specified bean.
   *
   * @param name the name of the bean.
   * @return the bean.
   * @throws InstanceNotFoundException if the name of the management bean
   *                                   could not be resolved.
   */
  private Object getBean(ObjectName name)
    throws InstanceNotFoundException
  {
    ServerInfo bean = beans.get(name);
    if (bean == null)
      throw new InstanceNotFoundException("The bean, " + name +
					  ", was not found.");
    return bean.getObject();
  }

  /**
   * Registers the supplied listener with the specified management
   * bean.  Notifications emitted by the management bean are forwarded
   * to the listener via the server, which will convert an MBean
   * references in the source to a portable {@link ObjectName}
   * instance.  The notification is otherwise unchanged.
   *
   * @param name the name of the management bean with which the listener
   *             should be registered.
   * @param listener the listener which will handle notifications from
   *                 the bean.
   * @param filter the filter to apply to incoming notifications, or
   *               <code>null</code> if no filtering should be applied.
   * @param passback an object to be passed to the listener when a
   *                 notification is emitted.
   * @throws InstanceNotFoundException if the name of the management bean
   *                                   could not be resolved.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "addNotificationListener")</code>}.
   * @see #removeNotificationListener(ObjectName, NotificationListener)
   * @see #removeNotificationListener(ObjectName, NotificationListener,
   *                                  NotificationFilter, Object)
   * @see NotificationBroadcaster#addNotificationListener(NotificationListener,
   *                                                      NotificationFilter,
   *                                                      Object)
   */
  public void addNotificationListener(ObjectName name, NotificationListener listener,
				      NotificationFilter filter, Object passback)
    throws InstanceNotFoundException
  {
    Object bean = getBean(name);
    checkSecurity(name, null, "addNotificationListener");
    if (bean instanceof NotificationBroadcaster)
      {
	NotificationBroadcaster bbean = (NotificationBroadcaster) bean;
	NotificationListener indirection = new ServerNotificationListener(bean, name,
									  listener);
	bbean.addNotificationListener(indirection, filter, passback);
	LazyListenersHolder.listeners.put(listener, indirection);
      }
  }

  /**
   * <p>
   * Registers the supplied listener with the specified management
   * bean.  Notifications emitted by the management bean are forwarded
   * to the listener via the server, which will convert any MBean
   * references in the source to portable {@link ObjectName}
   * instances.  The notification is otherwise unchanged.  
   * </p>
   * <p>
   * The listener that receives notifications will be the one that is
   * registered with the given name at the time this method is called.
   * Even if it later unregisters and ceases to use that name, it will
   * still receive notifications.
   * </p>
   *
   * @param name the name of the management bean with which the listener
   *             should be registered.
   * @param listener the name of the listener which will handle
   *                 notifications from the bean.
   * @param filter the filter to apply to incoming notifications, or
   *               <code>null</code> if no filtering should be applied.
   * @param passback an object to be passed to the listener when a
   *                 notification is emitted.
   * @throws InstanceNotFoundException if the name of the management bean
   *                                   could not be resolved.
   * @throws RuntimeOperationsException if the bean associated with the given
   *                                    object name is not a
   *                                    {@link NotificationListener}.  This
   *                                    exception wraps an
   *                                    {@link IllegalArgumentException}.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "addNotificationListener")</code>}.
   * @see #removeNotificationListener(ObjectName, NotificationListener)
   * @see #removeNotificationListener(ObjectName, NotificationListener,
   *                                  NotificationFilter, Object)
   * @see NotificationBroadcaster#addNotificationListener(NotificationListener,
   *                                                      NotificationFilter,
   *                                                      Object)
   */
  public void addNotificationListener(ObjectName name, ObjectName listener,
				      NotificationFilter filter, Object passback)
    throws InstanceNotFoundException
  {
    Object lbean = getBean(listener);
    if (!(lbean instanceof NotificationListener))
      {
	RuntimeException e =
	  new IllegalArgumentException("The supplied listener name does not " +
				       "correspond to a notification listener.");
	throw new RuntimeOperationsException(e);
      }
    addNotificationListener(name, ((NotificationListener) lbean), filter, passback);
  }

  /**
   * <p>
   * Instantiates a new instance of the specified management bean
   * using the default constructor and registers it with the server
   * under the supplied name.  The class is loaded using the
   * {@link javax.management.loading.ClassLoaderRepository default
   * loader repository} of the server. 
   * </p>
   * <p>
   * If the name supplied is <code>null</code>, then the bean is
   * expected to implement the {@link MBeanRegistration} interface.
   * The {@link MBeanRegistration#preRegister preRegister} method
   * of this interface will be used to obtain the name in this case.
   * </p>
   * <p>
   * This method is equivalent to calling {@link 
   * #createMBean(String, ObjectName, Object[], String[])
   * <code>createMBean(className, name, (Object[]) null,
   * (String[]) null)</code>} with <code>null</code> parameters
   * and signature.
   * </p>
   *
   * @param className the class of the management bean, of which
   *                  an instance should be created.
   * @param name the name to register the new bean with.
   * @return an {@link ObjectInstance} containing the {@link ObjectName}
   *         and Java class name of the created instance.
   * @throws ReflectionException if an exception occurs in creating
   *                             an instance of the bean.
   * @throws InstanceAlreadyExistsException if a matching instance
   *                                        already exists.
   * @throws MBeanRegistrationException if an exception occurs in
   *                                    calling the preRegister
   *                                    method.
   * @throws MBeanException if the bean's constructor throws an exception.
   * @throws NotCompliantMBeanException if the created bean is not
   *                                    compliant with the JMX specification.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> class name or object
   *                                    name or if the object name is a pattern.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply the
   *                           use of the <code>instantiate</code>
   *                           and <code>registerMBean</code> methods.
   * @see #createMBean(String, ObjectName, Object[], String[])
   */
  public ObjectInstance createMBean(String className, ObjectName name)
    throws ReflectionException, InstanceAlreadyExistsException,
	   MBeanRegistrationException, MBeanException,
	   NotCompliantMBeanException
  {
    return createMBean(className, name, (Object[]) null, (String[]) null);
  }
  
  /**
   * <p>
   * Instantiates a new instance of the specified management bean
   * using the given constructor and registers it with the server
   * under the supplied name.  The class is loaded using the
   * {@link javax.management.loading.ClassLoaderRepository default
   * loader repository} of the server. 
   * </p>
   * <p>
   * If the name supplied is <code>null</code>, then the bean is
   * expected to implement the {@link MBeanRegistration} interface.
   * The {@link MBeanRegistration#preRegister preRegister} method
   * of this interface will be used to obtain the name in this case.
   * </p>
   * 
   * @param className the class of the management bean, of which
   *                  an instance should be created.
   * @param name the name to register the new bean with.
   * @param params the parameters for the bean's constructor.
   * @param sig the signature of the constructor to use.
   * @return an {@link ObjectInstance} containing the {@link ObjectName}
   *         and Java class name of the created instance.
   * @throws ReflectionException if an exception occurs in creating
   *                             an instance of the bean.
   * @throws InstanceAlreadyExistsException if a matching instance
   *                                        already exists.
   * @throws MBeanRegistrationException if an exception occurs in
   *                                    calling the preRegister
   *                                    method.
   * @throws MBeanException if the bean's constructor throws an exception.
   * @throws NotCompliantMBeanException if the created bean is not
   *                                    compliant with the JMX specification.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> class name or object
   *                                    name or if the object name is a pattern.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply the
   *                           use of the <code>instantiate</code>
   *                           and <code>registerMBean</code> methods.
   */
  public ObjectInstance createMBean(String className, ObjectName name,
				    Object[] params, String[] sig)
    throws ReflectionException, InstanceAlreadyExistsException,
	   MBeanRegistrationException, MBeanException,
	   NotCompliantMBeanException
  {
    return registerMBean(instantiate(className, params, sig), name);
  } 

  /**
   * <p>
   * Instantiates a new instance of the specified management bean
   * using the default constructor and registers it with the server
   * under the supplied name.  The class is loaded using the
   * given class loader.  If this argument is <code>null</code>,
   * then the same class loader as was used to load the server
   * is used.
   * </p>
   * <p>
   * If the name supplied is <code>null</code>, then the bean is
   * expected to implement the {@link MBeanRegistration} interface.
   * The {@link MBeanRegistration#preRegister preRegister} method
   * of this interface will be used to obtain the name in this case.
   * </p>
   * <p>
   * This method is equivalent to calling {@link 
   * #createMBean(String, ObjectName, ObjectName, Object[], String)
   * <code>createMBean(className, name, loaderName, (Object[]) null,
   * (String) null)</code>} with <code>null</code> parameters
   * and signature.
   * </p>
   *
   * @param className the class of the management bean, of which
   *                  an instance should be created.
   * @param name the name to register the new bean with.
   * @param loaderName the name of the class loader.
   * @return an {@link ObjectInstance} containing the {@link ObjectName}
   *         and Java class name of the created instance.
   * @throws ReflectionException if an exception occurs in creating
   *                             an instance of the bean.
   * @throws InstanceAlreadyExistsException if a matching instance
   *                                        already exists.
   * @throws MBeanRegistrationException if an exception occurs in
   *                                    calling the preRegister
   *                                    method.
   * @throws MBeanException if the bean's constructor throws an exception.
   * @throws NotCompliantMBeanException if the created bean is not
   *                                    compliant with the JMX specification.
   * @throws InstanceNotFoundException if the specified class loader is not
   *                                   registered with the server.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> class name or object
   *                                    name or if the object name is a pattern.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply the
   *                           use of the <code>instantiate</code>
   *                           and <code>registerMBean</code> methods.
   * @see #createMBean(String, ObjectName, ObjectName, Object[], String[])
   */
  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);
  }

  /**
   * <p>
   * Instantiates a new instance of the specified management bean
   * using the given constructor and registers it with the server
   * under the supplied name.  The class is loaded using the
   * given class loader.  If this argument is <code>null</code>,
   * then the same class loader as was used to load the server
   * is used. 
   * </p>
   * <p>
   * If the name supplied is <code>null</code>, then the bean is
   * expected to implement the {@link MBeanRegistration} interface.
   * The {@link MBeanRegistration#preRegister preRegister} method
   * of this interface will be used to obtain the name in this case.
   * </p>
   * 
   * @param className the class of the management bean, of which
   *                  an instance should be created.
   * @param name the name to register the new bean with.
   * @param loaderName the name of the class loader.
   * @param params the parameters for the bean's constructor.
   * @param sig the signature of the constructor to use.
   * @return an {@link ObjectInstance} containing the {@link ObjectName}
   *         and Java class name of the created instance.
   * @throws ReflectionException if an exception occurs in creating
   *                             an instance of the bean.
   * @throws InstanceAlreadyExistsException if a matching instance
   *                                        already exists.
   * @throws MBeanRegistrationException if an exception occurs in
   *                                    calling the preRegister
   *                                    method.
   * @throws MBeanException if the bean's constructor throws an exception.
   * @throws NotCompliantMBeanException if the created bean is not
   *                                    compliant with the JMX specification.
   * @throws InstanceNotFoundException if the specified class loader is not
   *                                   registered with the server.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> class name or object
   *                                    name or if the object name is a pattern.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply the
   *                           use of the <code>instantiate</code>
   *                           and <code>registerMBean</code> methods.
   */
  public ObjectInstance createMBean(String className, ObjectName name,
				    ObjectName loaderName, Object[] params,
				    String[] sig)
    throws ReflectionException, InstanceAlreadyExistsException,
	   MBeanRegistrationException, MBeanException,
	   NotCompliantMBeanException, InstanceNotFoundException
  {
    return registerMBean(instantiate(className, loaderName, params, sig),
			 name);
  }

  /**
   * Deserializes a byte array using the class loader of the specified
   * management bean as its context.
   *
   * @param name the name of the bean whose class loader should be used.
   * @param data the byte array to be deserialized.
   * @return the deserialized object stream.
   * @deprecated {@link #getClassLoaderFor(ObjectName)} should be used
   *             to obtain the class loader of the bean, which can then
   *             be used to perform deserialization in the user's code.
   * @throws InstanceNotFoundException if the specified bean is not
   *                                   registered with the server.
   * @throws OperationsException if any I/O error is thrown by the
   *                             deserialization process.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "getClassLoaderFor")</code>
   */
  public ObjectInputStream deserialize(ObjectName name, byte[] data)
    throws InstanceNotFoundException, OperationsException
  {
    try
      {
	return new ServerInputStream(new ByteArrayInputStream(data),
				     getClassLoaderFor(name));
      }
    catch (IOException e)
      {
	throw new OperationsException("An I/O error occurred: " + e);
      }
  }

  /**
   * Deserializes a byte array using the same class loader for its context
   * as was used to load the given class.  This class loader is obtained by
   * loading the specified class using the {@link
   * javax.management.loading.ClassLoaderRepository Class Loader Repository}
   * and then using the class loader of the resulting {@link Class} instance.
   *
   * @param name the name of the class which should be loaded to obtain the
   *             class loader.
   * @param data the byte array to be deserialized.
   * @return the deserialized object stream.
   * @deprecated {@link #getClassLoaderRepository} should be used
   *             to obtain the class loading repository, which can then
   *             be used to obtain the {@link Class} instance and deserialize
   *             the array using its class loader.
   * @throws OperationsException if any I/O error is thrown by the
   *                             deserialization process.
   * @throws ReflectionException if an error occurs in obtaining the
   *                             {@link Class} instance.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(null, null, null,
   *                           "getClassLoaderRepository")</code>
   */
  public ObjectInputStream deserialize(String name, byte[] data)
    throws OperationsException, ReflectionException
  {
    try
      {
	Class<?> c = getClassLoaderRepository().loadClass(name);
	return new ServerInputStream(new ByteArrayInputStream(data),
					   c.getClassLoader());
      }
    catch (IOException e)
      {
	throw new OperationsException("An I/O error occurred: " + e);
      }
    catch (ClassNotFoundException e)
      {
	throw new ReflectionException(e, "The class could not be found.");
      }
  }

  /**
   * Deserializes a byte array using the same class loader for its context
   * as was used to load the given class.  The name of the class loader to
   * be used is supplied, and may be <code>null</code> if the server's
   * class loader should be used instead.
   *
   * @param name the name of the class which should be loaded to obtain the
   *             class loader.
   * @param loader the name of the class loader to use, or <code>null</code>
   *               if the class loader of the server should be used.
   * @param data the byte array to be deserialized.
   * @return the deserialized object stream.
   * @deprecated {@link #getClassLoader(ObjectName} can be used to obtain
   *              the named class loader and deserialize the array.
   * @throws InstanceNotFoundException if the specified class loader is not
   *                                   registered with the server.
   * @throws OperationsException if any I/O error is thrown by the
   *                             deserialization process.
   * @throws ReflectionException if an error occurs in obtaining the
   *                             {@link Class} instance.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, loader,
   *                           "getClassLoader")</code>
   */
  public ObjectInputStream deserialize(String name, ObjectName loader, byte[] data)
    throws InstanceNotFoundException, ReflectionException,
	   OperationsException
  {
    try
      {
	Class<?> c = getClassLoader(loader).loadClass(name);
	return new ServerInputStream(new ByteArrayInputStream(data),
					   c.getClassLoader());
      }
    catch (IOException e)
      {
	throw new OperationsException("An I/O error occurred: " + e);
      }
    catch (ClassNotFoundException e)
      {
	throw new ReflectionException(e, "The class could not be found.");
      }
  }

  /**
   * Returns the value of the supplied attribute from the specified
   * management bean.
   *
   * @param bean the bean to retrieve the value from.
   * @param name the name of the attribute to retrieve.
   * @return the value of the attribute.
   * @throws AttributeNotFoundException if the attribute could not be
   *                                    accessed from the bean.
   * @throws MBeanException if the management bean's accessor throws
   *                        an exception.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws ReflectionException if an exception was thrown in trying
   *                             to invoke the bean's accessor.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> bean or attribute
   *                                    name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, name, bean,
   *                           "getAttribute")</code>}.
   * @see DynamicMBean#getAttribute(String)
   */
  public Object getAttribute(ObjectName bean, String name)
    throws MBeanException, AttributeNotFoundException,
	   InstanceNotFoundException, ReflectionException
  {
    if (bean == null || name == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("One of the supplied arguments was null.");
	throw new RuntimeOperationsException(e);
      }
    Object abean = getBean(bean);
    checkSecurity(bean, name, "getAttribute");
    if (abean instanceof DynamicMBean)
      return ((DynamicMBean) abean).getAttribute(name);
    else
      try
	{
	  return new StandardMBean(abean, null).getAttribute(name);
	}
      catch (NotCompliantMBeanException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to create dynamic bean.").initCause(e));
	}
  }


  /**
   * Returns the values of the named attributes from the specified
   * management bean.
   *
   * @param bean the bean to retrieve the value from.
   * @param names the names of the attributes to retrieve.
   * @return the values of the attributes.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws ReflectionException if an exception was thrown in trying
   *                             to invoke the bean's accessor.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> bean or attribute
   *                                    name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, bean,
   *                           "getAttribute")</code>}.  Additionally,
   *                           for an attribute name, <code>n</code>, the
   *                           caller's permission must imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, n, bean,
   *                           "getAttribute")</code>} or that attribute will
   *                           not be included.
   *                           
   * @see DynamicMBean#getAttributes(String[])
   */
  public AttributeList getAttributes(ObjectName bean, String[] names)
    throws InstanceNotFoundException, ReflectionException
  {
    if (bean == null || names == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("One of the supplied arguments was null.");
	throw new RuntimeOperationsException(e);
      }
    Object abean = getBean(bean);
    checkSecurity(bean, null, "getAttribute");
    AttributeList list = new AttributeList(names.length);
    for (int a = 0; a < names.length; ++a)
      {
	if (names[a] == null)
	  {
	    RuntimeException e =
	      new IllegalArgumentException("Argument " + a + " was null.");
	    throw new RuntimeOperationsException(e);
	  }
	checkSecurity(bean, names[a], "getAttribute");
	try
	  {
	    Object value;
	    if (abean instanceof DynamicMBean)
	      value = ((DynamicMBean) abean).getAttribute(names[a]);
	    else
	      try
		{
		  value = new StandardMBean(abean, null).getAttribute(names[a]);
		}
	      catch (NotCompliantMBeanException e)
		{
		  throw (Error) 
		    (new InternalError("Failed to create dynamic bean.").initCause(e));
		}
	    list.add(new Attribute(names[a], value));
	  }
	catch (AttributeNotFoundException e)
	  {
	    /* Ignored */
	  }
	catch (MBeanException e)
	  {
	    /* Ignored */
	  }
      }
    return list;
  }


  /**
   * Returns the specified class loader.  If the specified value is
   * <code>null</code>, then the class loader of the server will be
   * returned.  If <code>l</code> is the requested class loader,
   * and <code>r</code> is the actual class loader returned, then
   * either <code>l</code> and <code>r</code> will be identical,
   * or they will at least return the same class from
   * {@link ClassLoader#loadClass(String)} for any given string.
   * They may not be identical due to one or the other
   * being wrapped in another class loader (e.g. for security).
   *
   * @param name the name of the class loader to return.
   * @return the class loader.
   * @throws InstanceNotFoundException if the class loader can not
   *                                   be found.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "getClassLoader")</code>
   */
  public ClassLoader getClassLoader(ObjectName name)
    throws InstanceNotFoundException
  {
    if (name == null)
      {
	checkSecurity(null, null, "getClassLoader");
	return getClass().getClassLoader();
      }
    Object bean = getBean(name);
    checkSecurity(name, null, "getClassLoader");
    return (ClassLoader) bean;
  }
 
  /**
   * Returns the class loader of the specified management bean.  If
   * <code>l</code> is the requested class loader, and <code>r</code>
   * is the actual class loader returned, then either <code>l</code>
   * and <code>r</code> will be identical, or they will at least
   * return the same class from {@link ClassLoader#loadClass(String)}
   * for any given string.  They may not be identical due to one or
   * the other being wrapped in another class loader (e.g. for
   * security).
   *
   * @param name the name of the bean whose class loader should be
   *             returned.
   * @return the class loader.
   * @throws InstanceNotFoundException if the bean is not registered
   *                                   with the server.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "getClassLoaderFor")</code>
   */
  public ClassLoader getClassLoaderFor(ObjectName name)
    throws InstanceNotFoundException
  {
    Object bean = getBean(name);
    checkSecurity(name, null, "getClassLoaderFor");
    return bean.getClass().getClassLoader();
  }    

  /**
   * Returns the class loader repository used by this server.
   *
   * @return the class loader repository.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(null, null, null,
   *                           "getClassLoaderRepository")</code>
   */
  public ClassLoaderRepository getClassLoaderRepository()
  {
    return repository;
  }

  /**
   * Returns the default domain this server applies to beans that have
   * no specified domain.
   *
   * @return the default domain.
   */
  public String getDefaultDomain()
  {
    return defaultDomain;
  }

  /**
   * Returns an array containing all the domains used by beans registered
   * with this server.  The ordering of the array is undefined.
   *
   * @return the list of domains.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(null, null, name,
   *                           "getDomains")</code>}.  Additionally,
   *                           for an domain, <code>d</code>, the
   *                           caller's permission must imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(null, null,
   *                           new ObjectName("d:x=x"), "getDomains")</code>}
   *                           or that domain will not be included.  Note
   *                           that "x=x" is an arbitrary key-value pair
   *                           provided to satisfy the constructor.
   * @see ObjectName#getDomain()
   */
  public String[] getDomains()
  {
    checkSecurity(null, null, "getDomains");
    Set<String> domains = new HashSet<String>();
    Iterator<ObjectName> iterator = beans.keySet().iterator();
    while (iterator.hasNext())
      {
	String d = iterator.next().getDomain();
	try
	  {
	    checkSecurity(new ObjectName(d + ":x=x"), null, "getDomains");
	    domains.add(d);
	  }
	catch (MalformedObjectNameException e)
	  {
	    /* Ignored */
	  }
      }
    return domains.toArray(new String[domains.size()]);
  }

  /**
   * Returns the number of management beans registered with this server.
   * This may be less than the real number if the caller's access is
   * restricted.
   *
   * @return the number of registered beans.
   */
  public Integer getMBeanCount()
  {
    return Integer.valueOf(beans.size());
  }

  /**
   * Returns information on the given management bean.
   *
   * @param name the name of the management bean.
   * @return an instance of {@link MBeanInfo} for the bean.
   * @throws IntrospectionException if an exception occurs in examining
   *                                the bean.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws ReflectionException if an exception occurs when trying
   *                             to invoke {@link DynamicMBean#getMBeanInfo()}
   *                             on the bean.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "getMBeanInfo")</code>}.
   * @see DynamicMBean#getMBeanInfo()
   */
  public MBeanInfo getMBeanInfo(ObjectName name)
    throws InstanceNotFoundException, IntrospectionException,
	   ReflectionException
  {
    Object bean = getBean(name);
    checkSecurity(name, null, "getMBeanInfo");
    try
      {
	Method method = bean.getClass().getMethod("getMBeanInfo");
	return (MBeanInfo) method.invoke(bean);
      }
    catch (NoSuchMethodException e)
      {
	try
	  {
	    return new StandardMBean(bean, null).getMBeanInfo();
	  }
	catch (NotCompliantMBeanException ex)
	  {
	    throw new IntrospectionException("An error occurred in executing " +
					     "getMBeanInfo on the bean: " + ex + ".");
	  }
      }
    catch (IllegalAccessException e)
      {
	throw new ReflectionException(e, "Failed to call getMBeanInfo");
      }
    catch (IllegalArgumentException e)
      {
	throw new ReflectionException(e, "Failed to call getMBeanInfo");
      }
    catch (InvocationTargetException e)
      {
	throw new ReflectionException(e, "The method threw an exception");
      }
  }

  /**
   * Returns the {@link ObjectInstance} created for the specified
   * management bean on registration.
   *
   * @param name the name of the bean.
   * @return the corresponding {@link ObjectInstance} instance.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "getObjectInstance")</code>
   * @see #createMBean(String, ObjectName)
   */
  public ObjectInstance getObjectInstance(ObjectName name)
    throws InstanceNotFoundException
  {
    ServerInfo bean = beans.get(name);
    if (bean == null)
      throw new InstanceNotFoundException("The bean, " + name +
					  ", was not found.");
    return bean.getInstance();
  }

  /**
   * <p>
   * Creates an instance of the specified class using the list of
   * class loaders from the {@link
   * javax.management.loading.ClassLoaderRepository Class Loader
   * Repository}.  The class should have a public constructor
   * with no arguments.  A reference to the new instance is returned,
   * but the instance is not yet registered with the server.
   * </p>
   * <p>
   * This method is equivalent to calling {@link 
   * #instantiate(String, Object[], String[])
   * <code>instantiate(name, (Object[]) null, (String[]) null)</code>}
   * with <code>null</code> parameters and signature.
   * </p>
   *
   * @param name the name of the class of bean to be instantiated.
   * @return an instance of the given class.
   * @throws ReflectionException if an exception is thrown during
   *                             loading the class or calling the
   *                             constructor.
   * @throws MBeanException if the constructor throws an exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, null,
   *                           "instantiate")</code>}.
   * @see #instantiate(String, Object[], String[])
   */
  public Object instantiate(String name)
    throws ReflectionException, MBeanException
  {
    return instantiate(name, (Object[]) null, (String[]) null);
  }

  /**
   * Creates an instance of the specified class using the list of
   * class loaders from the {@link
   * javax.management.loading.ClassLoaderRepository Class Loader
   * Repository}.  The class should have a public constructor
   * matching the supplied signature.  A reference to the new
   * instance is returned, but the instance is not yet
   * registered with the server.
   *
   * @param name the name of the class of bean to be instantiated.
   * @param params the parameters for the constructor.
   * @param sig the signature of the constructor.
   * @return an instance of the given class.
   * @throws ReflectionException if an exception is thrown during
   *                             loading the class or calling the
   *                             constructor.
   * @throws MBeanException if the constructor throws an exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, null,
   *                           "instantiate")</code>}.
   */
  public Object instantiate(String name, Object[] params, String[] sig)
    throws ReflectionException, MBeanException
  {
    checkSecurity(null, null, "instantiate");
    if (name == null)
      {
	RuntimeException e = 
	  new IllegalArgumentException("The name was null.");
	throw new RuntimeOperationsException(e);
      }
    Class<?>[] sigTypes = new Class[sig.length];
    for (int a = 0; a < sigTypes.length; ++a)
      {
	try 
	  {
	    sigTypes[a] = repository.loadClass(sig[a]);
	  }
	catch (ClassNotFoundException e)
	  {
	    throw new ReflectionException(e, "The class, " + sigTypes[a] + 
					  ", in the method signature " +
					  "could not be loaded.");
	  }
      }
    try
      {
	Constructor<?> cons =
	  repository.loadClass(name).getConstructor(sigTypes);
	return cons.newInstance(params);
      }
    catch (ClassNotFoundException e)
      {
	throw new ReflectionException(e, "The class, " + name + 
				      ", of the constructor " +
				      "could not be loaded.");
      }
    catch (NoSuchMethodException e)
      {
	throw new ReflectionException(e, "The method, " + name +
				      ", could not be found.");
      }
    catch (IllegalAccessException e)
      {
	throw new ReflectionException(e, "Failed to instantiate the object");
      }
    catch (InstantiationException e)
      {
	throw new ReflectionException(e, "Failed to instantiate the object");
      }
    catch (InvocationTargetException e)
      {
	throw new MBeanException((Exception) e.getCause(), "The constructor "
				 + name + " threw an exception");
      }
  }

  /**
   * <p>
   * Creates an instance of the specified class using the supplied
   * class loader.  If the class loader given is <code>null</code>,
   * then the class loader of the server will be used.  The class
   * should have a public constructor with no arguments.  A reference
   * to the new instance is returned, but the instance is not yet
   * registered with the server.
   * </p>
   * <p>
   * This method is equivalent to calling {@link 
   * #instantiate(String, ObjectName, Object[], String[])
   * <code>instantiate(name, loaderName, (Object[]) null,
   * (String[]) null)</code>} with <code>null</code> parameters
   * and signature.
   * </p>
   *
   * @param name the name of the class of bean to be instantiated.
   * @param loaderName the name of the class loader to use.
   * @return an instance of the given class.
   * @throws InstanceNotFoundException if the class loader is not
   *                                   registered with the server.
   * @throws ReflectionException if an exception is thrown during
   *                             loading the class or calling the
   *                             constructor.
   * @throws MBeanException if the constructor throws an exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, null,
   *                           "instantiate")</code>}.
   * @see #instantiate(String, Object[], String[])
   */
  public Object instantiate(String name, ObjectName loaderName)
    throws InstanceNotFoundException, ReflectionException,
	   MBeanException
  {
    return instantiate(name, loaderName);
  }

  /**
   * Creates an instance of the specified class using the supplied
   * class loader.  If the class loader given is <code>null</code>,
   * then the class loader of the server will be used.  The class
   * should have a public constructor matching the supplied
   * signature.  A reference to the new instance is returned,
   * but the instance is not yet registered with the server.
   *
   * @param name the name of the class of bean to be instantiated.
   * @param loaderName the name of the class loader to use.
   * @param params the parameters for the constructor.
   * @param sig the signature of the constructor.
   * @return an instance of the given class.
   * @throws InstanceNotFoundException if the class loader is not
   *                                   registered with the server.
   * @throws ReflectionException if an exception is thrown during
   *                             loading the class or calling the
   *                             constructor.
   * @throws MBeanException if the constructor throws an exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, null,
   *                           "instantiate")</code>}.
   */
  public Object instantiate(String name, ObjectName loaderName,
			    Object[] params, String[] sig)
    throws InstanceNotFoundException, ReflectionException,
	   MBeanException
  {
    checkSecurity(null, null, "instantiate");
    if (name == null)
      {
	RuntimeException e = 
	  new IllegalArgumentException("The name was null.");
	throw new RuntimeOperationsException(e);
      }
    ClassLoader loader = getClassLoader(loaderName);
    Class<?>[] sigTypes = new Class[sig.length];
    for (int a = 0; a < sig.length; ++a)
      {
	try 
	  {
	    sigTypes[a] = Class.forName(sig[a], true, loader);
	  }
	catch (ClassNotFoundException e)
	  {
	    throw new ReflectionException(e, "The class, " + sig[a] + 
					  ", in the method signature " +
					  "could not be loaded.");
	  }
      }
    try
      {
	Constructor<?> cons =
	  Class.forName(name, true, loader).getConstructor(sigTypes);
	return cons.newInstance(params);
      }
    catch (ClassNotFoundException e)
      {
	throw new ReflectionException(e, "The class, " + name + 
				      ", of the constructor " +
				      "could not be loaded.");
      }
    catch (NoSuchMethodException e)
      {
	throw new ReflectionException(e, "The method, " + name +
				      ", could not be found.");
      }
    catch (IllegalAccessException e)
      {
	throw new ReflectionException(e, "Failed to instantiate the object");
      }
    catch (InstantiationException e)
      {
	throw new ReflectionException(e, "Failed to instantiate the object");
      }
    catch (InvocationTargetException e)
      {
	throw new MBeanException((Exception) e.getCause(), "The constructor "
				 + name + " threw an exception");
      }
  }

  /**
   * Invokes the supplied operation on the specified management
   * bean.  The class objects specified in the signature are loaded
   * using the same class loader as was used for the management bean.
   *
   * @param bean the management bean whose operation should be invoked.
   * @param name the name of the operation to invoke.
   * @param params the parameters of the operation.
   * @param sig the signature of the operation.
   * @return the return value of the method.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws MBeanException if the method invoked throws an exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> name.
   * @throws ReflectionException if an exception is thrown in invoking the
   *                             method.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, name, bean,
   *                           "invoke")</code>}.
   * @see DynamicMBean#invoke(String, Object[], String[])
   */
  public Object invoke(ObjectName bean, String name, Object[] params, String[] sig)
    throws InstanceNotFoundException, MBeanException,
	   ReflectionException
  {
    if (bean == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("The bean was null.");
	throw new RuntimeOperationsException(e);
      }
    Object abean = getBean(bean);
    checkSecurity(bean, name, "invoke");
    if (abean instanceof DynamicMBean)
      return ((DynamicMBean) abean).invoke(name, params, sig);
    else
      try
	{
	  return new StandardMBean(abean, null).invoke(name, params, sig);
	}
      catch (NotCompliantMBeanException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to create dynamic bean.").initCause(e));
	}
  }

  /**
   * <p>
   * Returns true if the specified management bean is an instance
   * of the supplied class.
   * </p>
   * <p>
   * A bean, B, is an instance of a class, C, if either of the following
   * conditions holds:
   * </p>
   * <ul>
   * <li>The class name in B's {@link MBeanInfo} is equal to the supplied
   * name.</li>
   * <li>Both the class of B and C were loaded by the same class loader,
   * and B is assignable to C.</li>
   * </ul>
   * 
   * @param name the name of the management bean.
   * @param className the name of the class to test if <code>name</code> is
   *                  an instance of.
   * @return true if either B is directly an instance of the named class,
   *         or B is assignable to the class, given that both it and B's
   *         current class were loaded using the same class loader.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "isInstanceOf")</code>
   */
  public boolean isInstanceOf(ObjectName name, String className)
    throws InstanceNotFoundException
  {
    Object bean = getBean(name);
    checkSecurity(name, null, "isInstanceOf");
    MBeanInfo info;
    if (bean instanceof DynamicMBean)
      info = ((DynamicMBean) bean).getMBeanInfo();
    else
      try
	{
	  info = new StandardMBean(bean, null).getMBeanInfo();
	}
      catch (NotCompliantMBeanException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to create dynamic bean.").initCause(e));
	}
    if (info.getClassName().equals(className))
      return true;
    Class<?> bclass = bean.getClass();
    try
      {
	Class<?> oclass = Class.forName(className);
	return (bclass.getClassLoader().equals(oclass.getClassLoader()) &&
		oclass.isAssignableFrom(bclass));  
      }
    catch (ClassNotFoundException e)
      {
	return false;
      }
  }

  /**
   * Returns true if the specified management bean is registered with
   * the server.
   *
   * @param name the name of the management bean.
   * @return true if the bean is registered.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> bean name.
   */
  public boolean isRegistered(ObjectName name)
  {
    if (name == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("The name was null.");
	throw new RuntimeOperationsException(e);
      }
    return beans.containsKey(name);
  }

  /**
   * <p>
   * Returns a set of {@link ObjectInstance}s matching the specified
   * criteria.  The full set of beans registered with the server
   * are passed through two filters:
   * </p>
   * <ol>
   * <li>Pattern matching is performed using the supplied
   * {@link ObjectName}.</li>
   * <li>The supplied query expression is applied.</li>
   * </ol>
   * <p>
   * If both the object name and the query expression are <code>null</code>,
   * or the object name has no domain and no key properties,
   * no filtering will be performed and all beans are returned. 
   * </p>
   *
   * @param name an {@link ObjectName} to use as a filter.
   * @param query a query expression to apply to each of the beans that match
   *              the given object name.
   * @return a set of {@link ObjectInstance}s matching the filtered beans.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(null, null, name,
   *                           "queryMBeans")</code>}.  Additionally,
   *                           for an bean, <code>b</code>, the
   *                           caller's permission must imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, b, name,
   *                           "queryMBeans")</code>} or that bean will
   *                           not be included.  Such an exception may also
   *                           arise from the execution of the query, in which
   *                           case that particular bean will again be excluded.
   */
  public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query)
  {
    checkSecurity(name, null, "queryMBeans");
    Set<ObjectInstance> results = new HashSet<ObjectInstance>();
    for (Map.Entry<ObjectName,ServerInfo> entry : beans.entrySet())
      {
	ObjectName nextName = entry.getKey();
	checkSecurity(name, nextName.toString(), "queryMBeans");
	try
	  {
	    if ((name == null || name.apply(nextName)) &&
		(query == null || query.apply(nextName)))
	      results.add(entry.getValue().getInstance());
	  }
	catch (BadStringOperationException e)
	  {
	    /* Ignored -- assume false result */
	  }
	catch (BadBinaryOpValueExpException e)
	  {
	    /* Ignored -- assume false result */
	  }
	catch (BadAttributeValueExpException e)
	  {
	    /* Ignored -- assume false result */
	  }
	catch (InvalidApplicationException e)
	  {
	    /* Ignored -- assume false result */
	  }
      }
    return results;
  }
 
  /**
   * <p>
   * Returns a set of {@link ObjectName}s matching the specified
   * criteria.  The full set of beans registered with the server
   * are passed through two filters:
   * </p>
   * <ol>
   * <li>Pattern matching is performed using the supplied
   * {@link ObjectName}.</li>
   * <li>The supplied query expression is applied.</li>
   * </ol>
   * <p>
   * If both the object name and the query expression are <code>null</code>,
   * or the object name has no domain and no key properties,
   * no filtering will be performed and all beans are returned. 
   * </p>
   *
   * @param name an {@link ObjectName} to use as a filter.
   * @param query a query expression to apply to each of the beans that match
   *              the given object name.
   * @return a set of {@link ObjectName}s matching the filtered beans.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(null, null, name,
   *                           "queryNames")</code>}.  Additionally,
   *                           for an name, <code>n</code>, the
   *                           caller's permission must imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, n, name,
   *                           "queryNames")</code>} or that name will
   *                           not be included.  Such an exception may also
   *                           arise from the execution of the query, in which
   *                           case that particular bean will again be excluded.
   *                           Note that these permissions are implied if the
   *                           <code>queryMBeans</code> permissions are available.
   */
  public Set<ObjectName> queryNames(ObjectName name, QueryExp query)
  {
    checkSecurity(name, null, "queryNames");
    Set<ObjectName> results = new HashSet<ObjectName>();
    for (ObjectName nextName : beans.keySet())
      {
	checkSecurity(name, nextName.toString(), "queryNames");
	try
	  {
	    if ((name == null || name.apply(nextName)) &&
		(query == null || query.apply(nextName)))
	      results.add(nextName);
	  }
	catch (BadStringOperationException e)
	  {
	    /* Ignored -- assume false result */
	  }
	catch (BadBinaryOpValueExpException e)
	  {
	    /* Ignored -- assume false result */
	  }
	catch (BadAttributeValueExpException e)
	  {
	    /* Ignored -- assume false result */
	  }
	catch (InvalidApplicationException e)
	  {
	    /* Ignored -- assume false result */
	  }
      }
    return results;
  }

  /**
   * Registers the supplied instance with the server, using the specified
   * {@link ObjectName}.  If the name given is <code>null</code>, then
   * the bean supplied is expected to implement the {@link MBeanRegistration}
   * interface and provide the name via the 
   * {@link MBeanRegistration#preRegister preRegister} method
   * of this interface.
   *
   * @param obj the object to register with the server.
   * @param name the name under which to register the object,
   *             or <code>null</code> if the {@link MBeanRegistration}
   *             interface should be used.
   * @return an {@link ObjectInstance} containing the supplied
   *         {@link ObjectName} along with the name of the bean's class.
   * @throws InstanceAlreadyExistsException if a matching instance
   *                                        already exists.
   * @throws MBeanRegistrationException if an exception occurs in
   *                                    calling the preRegister
   *                                    method.
   * @throws NotCompliantMBeanException if the created bean is not
   *                                    compliant with the JMX specification.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> object.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "registerMBean")</code>}.  <code>className</code>
   *                           here corresponds to the result of
   *                           {@link MBeanInfo#getClassName()} for objects of
   *                           this class.  If this check succeeds, a check
   *                           is also made on its
   *                           {@link java.security.ProtectionDomain} to ensure
   *                           it implies {@link MBeanTrustPermission(String)
   *                           <code>MBeanTrustPermission("register")</code>}.
   *                           The use of the {@link MBeanRegistration} interface
   *                           results in another {@link MBeanPermission} check
   *                           being made on the returned {@link ObjectName}.
   */
  public ObjectInstance registerMBean(Object obj, ObjectName name)
    throws InstanceAlreadyExistsException, MBeanRegistrationException,
	   NotCompliantMBeanException
  {  
    SecurityManager sm = System.getSecurityManager();
    Class<?> cl = obj.getClass();
    String className = cl.getName();
    if (sm != null)
      {
	sm.checkPermission(new MBeanPermission(className, null, name,
					       "registerMBean"));
	if (!(cl.getProtectionDomain().implies(new MBeanTrustPermission("register"))))
	  throw new SecurityException("The protection domain of the object's class" +
				      "does not imply the trust permission," +
				      "register");
      }
    if (obj == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("The object was null.");
	throw new RuntimeOperationsException(e);
      }
    MBeanRegistration register = null;
    if (obj instanceof MBeanRegistration)
      register = (MBeanRegistration) obj;
    if (name == null && register == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("The name was null and " +
				       "the bean does not implement " +
				       "MBeanRegistration.");
	throw new RuntimeOperationsException(e);
      }
    if (register != null)
      {
	try
	  {
	    name = register.preRegister(this, name);
	    if (name == null)
	      {
		RuntimeException e =
		  new NullPointerException("The name returned by " +
					   "MBeanRegistration.preRegister() " +
					   "was null");
		throw e;
	      }
	    if (sm != null)
	      sm.checkPermission(new MBeanPermission(className, null, name,
						     "registerMBean"));
	  }
	catch (SecurityException e)
	  {
	    register.postRegister(Boolean.FALSE);
	    throw e;
	  }
	catch (Exception e)
	  {
	    register.postRegister(Boolean.FALSE);
	    throw new MBeanRegistrationException(e, "Pre-registration failed.");
	  }
      }
    ObjectInstance obji = new ObjectInstance(name, className);
    if (beans.putIfAbsent(name, new ServerInfo(obji, obj)) != null)
      {
	if (register != null)
	  register.postRegister(Boolean.FALSE);
	throw new InstanceAlreadyExistsException(name + "is already registered.");
      }
    if (register != null)
      register.postRegister(Boolean.TRUE);
    notify(name, MBeanServerNotification.REGISTRATION_NOTIFICATION);
    return obji;
  }

  /**
   * Removes the specified listener from the list of recipients
   * of notifications from the supplied bean.  This includes all
   * combinations of filters and passback objects registered for
   * this listener.  For more specific removal of listeners, see
   * {@link #removeNotificationListener(ObjectName,
   * NotificationListener,NotificationFilter,Object)}
   *
   * @param name the name of the management bean from which the
   *             listener should be removed.
   * @param listener the listener to remove.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws ListenerNotFoundException if the specified listener
   *                                   is not registered with the bean.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "removeNotificationListener")</code>}.
   * @see #addNotificationListener(NotificationListener, NotificationFilter,
   *                               java.lang.Object)
   * @see NotificationBroadcaster#removeNotificationListener(NotificationListener)
   */
  public void removeNotificationListener(ObjectName name,
					 NotificationListener listener)
    throws InstanceNotFoundException, ListenerNotFoundException
  {
    Object bean = getBean(name);
    checkSecurity(name, null, "removeNotificationListener");
    if (bean instanceof NotificationBroadcaster)
      {
	NotificationBroadcaster bbean = (NotificationBroadcaster) bean;
	bbean.removeNotificationListener(listener);
	LazyListenersHolder.listeners.remove(listener);
      }
  }

  /**
   * Removes the specified listener from the list of recipients
   * of notifications from the supplied bean.  Only the first instance with
   * the supplied filter and passback object is removed.
   * <code>null</code> is used as a valid value for these parameters,
   * rather than as a way to remove all registration instances for
   * the specified listener; for this behaviour instead, see
   * {@link #removeNotificationListener(ObjectName, NotificationListener)}.
   *
   * @param name the name of the management bean from which the
   *             listener should be removed.
   * @param listener the listener to remove.
   * @param filter the filter of the listener to remove.
   * @param passback the passback object of the listener to remove.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws ListenerNotFoundException if the specified listener
   *                                   is not registered with the bean.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "removeNotificationListener")</code>}.
   * @see #addNotificationListener(ObjectName, NotificationListener,
   *                               NotificationFilter, Object)
   * @see NotificationEmitter#removeNotificationListener(NotificationListener,
   *                                                     NotificationFilter,
   *                                                     Object)
   */
  public void removeNotificationListener(ObjectName name,
					 NotificationListener listener,
					 NotificationFilter filter,
					 Object passback)
    throws InstanceNotFoundException, ListenerNotFoundException
  {
    Object bean = getBean(name);
    checkSecurity(name, null, "removeNotificationListener");
    if (bean instanceof NotificationEmitter)
      {
	NotificationEmitter bbean = (NotificationEmitter) bean;
	bbean.removeNotificationListener(listener, filter, passback);
	LazyListenersHolder.listeners.remove(listener);
      }
  }

  /**
   * Removes the specified listener from the list of recipients
   * of notifications from the supplied bean.  This includes all
   * combinations of filters and passback objects registered for
   * this listener.  For more specific removal of listeners, see
   * {@link #removeNotificationListener(ObjectName,
   * ObjectName,NotificationFilter,Object)}
   *
   * @param name the name of the management bean from which the
   *             listener should be removed.
   * @param listener the name of the listener to remove.
   * @throws InstanceNotFoundException if a name doesn't match a registered
   *                                   bean.
   * @throws ListenerNotFoundException if the specified listener
   *                                   is not registered with the bean.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "removeNotificationListener")</code>}.
   * @see #addNotificationListener(NotificationListener, NotificationFilter,
   *                               java.lang.Object)
   * @see NotificationBroadcaster#removeNotificationListener(NotificationListener)
   */
  public void removeNotificationListener(ObjectName name, ObjectName listener)
    throws InstanceNotFoundException, ListenerNotFoundException
  {
    Object lbean = getBean(listener);
    if (!(lbean instanceof NotificationListener))
      {
	RuntimeException e =
	  new IllegalArgumentException("The supplied listener name does not " +
				       "correspond to a notification listener.");
	throw new RuntimeOperationsException(e);
      }
    removeNotificationListener(name, ((NotificationListener) lbean));
  }

  /**
   * Removes the specified listener from the list of recipients
   * of notifications from the supplied bean.  Only the first instance with
   * the supplied filter and passback object is removed.
   * <code>null</code> is used as a valid value for these parameters,
   * rather than as a way to remove all registration instances for
   * the specified listener; for this behaviour instead, see
   * {@link #removeNotificationListener(ObjectName, ObjectName)}.
   *
   * @param name the name of the management bean from which the
   *             listener should be removed.
   * @param listener the name of the listener to remove.
   * @param filter the filter of the listener to remove.
   * @param passback the passback object of the listener to remove.
   * @throws InstanceNotFoundException if a name doesn't match a registered
   *                                   bean.
   * @throws ListenerNotFoundException if the specified listener
   *                                   is not registered with the bean.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "removeNotificationListener")</code>}.
   * @see #addNotificationListener(ObjectName, NotificationListener,
   *                               NotificationFilter, Object)
   * @see NotificationEmitter#removeNotificationListener(NotificationListener,
   *                                                     NotificationFilter,
   *                                                     Object)
   */
  public void removeNotificationListener(ObjectName name,
				  ObjectName listener,
				  NotificationFilter filter,
				  Object passback)
    throws InstanceNotFoundException, ListenerNotFoundException
  {
    Object lbean = getBean(listener);
    if (!(lbean instanceof NotificationListener))
      {
	RuntimeException e =
	  new IllegalArgumentException("The supplied listener name does not " +
				       "correspond to a notification listener.");
	throw new RuntimeOperationsException(e);
      }
    removeNotificationListener(name, ((NotificationListener) lbean), filter,
			       passback);
  }

  /**
   * Sets the value of the specified attribute of the supplied
   * management bean.  
   *
   * @param name the name of the management bean.
   * @param attribute the attribute to set.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws AttributeNotFoundException if the attribute does not
   *                                    correspond to an attribute
   *                                    of the bean.
   * @throws InvalidAttributeValueException if the value is invalid
   *                                        for this particular
   *                                        attribute of the bean.
   * @throws MBeanException if setting the attribute causes
   *                        the bean to throw an exception (which
   *                        becomes the cause of this exception).
   * @throws ReflectionException if an exception occurred in trying
   *                             to use the reflection interface
   *                             to lookup the attribute.  The
   *                             thrown exception is the cause of
   *                             this exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> bean or attribute
   *                                    name.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, name, bean,
   *                           "setAttribute")</code>}.
   * @see #getAttribute(ObjectName, String)
   * @see DynamicMBean#setAttribute(Attribute)
   */
  public void setAttribute(ObjectName name, Attribute attribute)
    throws InstanceNotFoundException, AttributeNotFoundException,
	   InvalidAttributeValueException, MBeanException,
	   ReflectionException
  {
    if (attribute == null || name == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("One of the supplied arguments was null.");
	throw new RuntimeOperationsException(e);
      }
    Object bean = getBean(name);
    checkSecurity(name, attribute.getName(), "setAttribute");
    if (bean instanceof DynamicMBean)
      ((DynamicMBean) bean).setAttribute(attribute);
    else
      try
	{
	  new StandardMBean(bean, null).setAttribute(attribute);
	}
      catch (NotCompliantMBeanException e)
	{
	  throw (Error) 
	    (new InternalError("Failed to create dynamic bean.").initCause(e));
	}
  }

  /**
   * Sets the value of each of the specified attributes
   * of the supplied management bean to that specified by
   * the {@link Attribute} object.  The returned list contains
   * the attributes that were set and their new values.
   *
   * @param name the name of the management bean.
   * @param attributes the attributes to set.
   * @return a list of the changed attributes.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws ReflectionException if an exception occurred in trying
   *                             to use the reflection interface
   *                             to lookup the attribute.  The
   *                             thrown exception is the cause of
   *                             this exception.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> bean or attribute
   *                                    list.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, bean,
   *                           "setAttribute")</code>}.  Additionally,
   *                           for an attribute name, <code>n</code>, the
   *                           caller's permission must imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, n, bean,
   *                           "setAttribute")</code>} or that attribute will
   *                           not be included.
   * @see #getAttributes(ObjectName, String[])
   * @see DynamicMBean#setAttributes(AttributeList)
   */
  public AttributeList setAttributes(ObjectName name, AttributeList attributes)
    throws InstanceNotFoundException, ReflectionException
  {
    if (name == null || attributes == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("One of the supplied arguments was null.");
	throw new RuntimeOperationsException(e);
      }
    Object abean = getBean(name);
    checkSecurity(name, null, "setAttribute");
    AttributeList list = new AttributeList(attributes.size());
    Iterator<Object> it = attributes.iterator();
    while (it.hasNext())
      {
	try
	  {
	    Attribute attrib = (Attribute) it.next();
	    if (attrib == null)
	      {
		RuntimeException e =
		  new IllegalArgumentException("An attribute was null.");
		throw new RuntimeOperationsException(e);
	      }
	    checkSecurity(name, attrib.getName(), "setAttribute");
	    if (abean instanceof DynamicMBean)
	      ((DynamicMBean) abean).setAttribute(attrib);
	    else
	      try
		{
		  new StandardMBean(abean, null).setAttribute(attrib);
		}
	      catch (NotCompliantMBeanException e)
		{
		  throw (Error) 
		    (new InternalError("Failed to create dynamic bean.").initCause(e));
		}
	    list.add(attrib);
	  }
	catch (AttributeNotFoundException e)
	  {
	    /* Ignored */
	  }
	catch (InvalidAttributeValueException e)
	  {
	    /* Ignored */
	  }
	catch (MBeanException e)
	  {
	    /* Ignored */
	  }
      }
    return list;
  }

  /**
   * Unregisters the specified management bean.  Following this operation,
   * the bean instance is no longer accessible from the server via this
   * name.  Prior to unregistering the bean, the
   * {@link MBeanRegistration#preDeregister()} method will be called if
   * the bean implements the {@link MBeanRegistration} interface.
   *
   * @param name the name of the management bean.
   * @throws InstanceNotFoundException if the bean can not be found.
   * @throws MBeanRegistrationException if an exception occurs in
   *                                    calling the preDeregister
   *                                    method.
   * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
   *                                    is thrown by the server due to a
   *                                    <code>null</code> bean name or a
   *                                    request being made to unregister the
   *                                    {@link MBeanServerDelegate} bean.
   * @throws SecurityException if a security manager exists and the
   *                           caller's permissions don't imply {@link
   *                           MBeanPermission(String,String,ObjectName,String)
   *                           <code>MBeanPermission(className, null, name,
   *                           "unregisterMBean")</code>}.
   */ 
  public void unregisterMBean(ObjectName name)
    throws InstanceNotFoundException, MBeanRegistrationException
  {
    if (name == null)
      {
	RuntimeException e =
	  new IllegalArgumentException("The name was null.");
	throw new RuntimeOperationsException(e);
      }
    if (name.equals(DELEGATE_NAME))
      {
	RuntimeException e =
	  new IllegalArgumentException("The delegate can not be unregistered.");
	throw new RuntimeOperationsException(e);
      }	
    Object bean = getBean(name);    
    checkSecurity(name, null, "unregisterMBean");
    MBeanRegistration register = null;
    if (bean instanceof MBeanRegistration)
      {
	register = (MBeanRegistration) bean;
	try
	  {
	    register.preDeregister();
	  }
	catch (Exception e)
	  {
	    throw new MBeanRegistrationException(e, "Pre-deregistration failed.");
	  }
      }
    beans.remove(name);
    notify(name, MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
    if (register != null)
      register.postDeregister();
  }

  /**
   * Notifies the delegate of beans being registered
   * and unregistered.
   *
   * @param name the bean being registered.
   * @param type the type of notification;
   * {@code REGISTRATION_NOTIFICATION} or
   * {@code UNREGISTRATION_NOTIFICATION}.
   */
   private void notify(ObjectName name, String type)
   {
      delegate.sendNotification
	(new MBeanServerNotification
	 (type, DELEGATE_NAME, sequenceNumber.getAndIncrement(), name));
   }

  /**
   * Input stream which deserializes using the given classloader.
   */
  private class ServerInputStream
    extends ObjectInputStream
  {

    private ClassLoader cl;

    public ServerInputStream(InputStream is, ClassLoader cl)
      throws IOException, StreamCorruptedException
    {
      super(is);
      this.cl = cl;
    }

    protected Class<?> resolveClass(ObjectStreamClass osc)
      throws ClassNotFoundException, IOException
    {
      try
	{
	  return Class.forName(osc.getName(), true, cl);
	}
      catch (ClassNotFoundException e)
	{
	  return super.resolveClass(osc);
	}
    }

  }

  /**
   * Holder for information on registered beans.
   */
  private class ServerInfo
  {  
    private ObjectInstance instance;

    private Object object;

    public ServerInfo(ObjectInstance instance, Object object)
    {
      this.instance = instance;
      this.object = object;
    }

    public Object getObject()
    {
      return object;
    }

    public ObjectInstance getInstance()
    {
      return instance;
    }
  }

  /**
   * Notification listener which removes direct references
   * to beans.
   */
  private class ServerNotificationListener
    implements NotificationListener
  {

    /**
     * The bean from which notifications are emitted.
     */
    Object bean;

    /**
     * The {@link ObjectName} of the emitting bean.
     */
    ObjectName name;

    /**
     * The real {@link NotificationListener}.
     */
    NotificationListener listener;

    /**
     * Constructs a new {@link ServerNotificationListener} replacing
     * occurrences of <code>bean</code> with its name.
     *
     * @param bean the bean emitting notifications.
     * @param name the object name of the emitting bean.
     * @param listener the listener events eventually reach.
     */
    public ServerNotificationListener(Object bean, ObjectName name,
				      NotificationListener listener)
    {
      this.bean = bean;
      this.name = name;
      this.listener = listener;
    }

    /**
     * Replace a direct reference to <code>bean</code> with its
     * object reference, if necessary, before calling the listener.
     *
     * @param notif the notification being emitted.
     * @param handback an object that will be returned to the notification
     *                 listener when an event occurs.
     */
    public void handleNotification(Notification notif, Object handback)
    {
      if (notif.getSource() == bean)
	notif.setSource(name);
      listener.handleNotification(notif, handback);
    }

  }

}
