this as the instance.  This should
   * be used to create an instance via subclassing.
   *
   * @param iface the interface this bean implements, or null
   *              if the interface should be determined using the naming
   *              convention (class X has interface XMBean).
   * @throws NotCompliantMBeanException if this class doesn't implement
   *                                    the interface or a method appears
   *                                    in the interface that doesn't comply
   *                                    with the naming conventions.
   */
  protected StandardMBean(Class> iface)
    throws NotCompliantMBeanException
  {
    if (iface == null)
      {
        String className = getClass().getName();
        try
          {
            iface = Class.forName(className + "MBean");
          }
        catch (ClassNotFoundException e)
          {
            for (Class> nextIface : getClass().getInterfaces())
            {
              if (JMX.isMXBeanInterface(nextIface))
                {
                  iface = nextIface;
                  break;
                }
            }
            if (iface == null)
              throw (NotCompliantMBeanException)
                (new NotCompliantMBeanException("An interface for the class "
                                                + className +
                                                " was not found.").initCause(e));
          }
      }
    if (!(iface.isInstance(this)))
      throw new NotCompliantMBeanException("The instance, " + impl +
                                           ", is not an instance of " + iface);
    impl = this;
    this.iface = iface;
  }
  /**
   * Constructs a new {@link StandardMBean} using the specified
   * interface and the supplied instance as the implementation.
   *
   * @param impl the implementation.
   * @param iface the interface the bean implements, or null
   *              if the interface should be determined using the naming
   *              convention (class X has interface XMBean).
   * @throws IllegalArgumentException if impl is null.
   * @throws NotCompliantMBeanException if impl doesn't implement
   *                                    the interface or a method appears
   *                                    in the interface that doesn't comply
   *                                    with the naming conventions.
   */
  public null
   *             if there is no new value to cache.  When the value is not
   *             null, the cache should replace the current value
   *             with the value supplied here.
   * @see #getCachedMBeanInfo()
   */
  protected void cacheMBeanInfo(MBeanInfo info)
  {
    if (info != null)
      this.info = info;
  }
  /**
   * Obtains the value of the specified attribute of the
   * management bean.  The management bean should perform
   * a lookup for the named attribute, and return its value
   * by calling the appropriate getter method, if possible.
   *
   * @param name the name of the attribute to retrieve.
   * @return the value of the specified attribute.
   * @throws AttributeNotFoundException if the name does not
   *                                    correspond to an attribute
   *                                    of the bean.
   * @throws MBeanException if retrieving 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.
   * @see #setAttribute(String)
   */
  public Object getAttribute(String name)
    throws AttributeNotFoundException, MBeanException,
           ReflectionException
  {
    Method getter;
    try
      {
        getter = iface.getMethod("get" + name);
      }
    catch (NoSuchMethodException e)
      {
        try
          {
            getter = iface.getMethod("is" + name);
          }
        catch (NoSuchMethodException ex)
          {
            throw ((AttributeNotFoundException)
                   new AttributeNotFoundException("The attribute, " + name +
                                                  ", was not found.").initCause(ex));
          }
      }
    Object result;
    try
      {
        result = getter.invoke(impl);
      }
    catch (IllegalAccessException e)
      {
        throw new ReflectionException(e, "Failed to retrieve " + name);
      }
    catch (IllegalArgumentException e)
      {
        throw new ReflectionException(e, "Failed to retrieve " + name);
      }
    catch (InvocationTargetException e)
      {
        throw new MBeanException((Exception) e.getCause(),
                                 "The getter of " + name +
                                 " threw an exception");
      }
    return result;
  }
  /**
   * Obtains the values of each of the specified attributes
   * of the management bean.  The returned list includes
   * those attributes that were retrieved and their
   * corresponding values.
   *
   * @param names the names of the attributes to retrieve.
   * @return a list of the retrieved attributes.
   * @see #setAttributes(AttributeList)
   */
  public AttributeList getAttributes(String[] names)
  {
    AttributeList list = new AttributeList(names.length);
    for (int a = 0; a < names.length; ++a)
      {
        try
          {
            Object value = getAttribute(names[a]);
            list.add(new Attribute(names[a], value));
          }
        catch (AttributeNotFoundException e)
          {
            /* Ignored */
          }
        catch (ReflectionException e)
          {
            /* Ignored */
          }
        catch (MBeanException e)
          {
            /* Ignored */
          }
      }
    return list;
  }
  /**
   * Returns the cached {@link MBeanInfo} instance for this object.  This is a
   * customization hook, so that subclasses can choose the caching policy
   * used.  The default implementation caches the value in the instance
   * itself, and returns this value on calls to this method.
   *
   * @return the cached {@link MBeanInfo} instance, or null
   *         if no value is cached.
   * @see #cacheMBeanInfo(javax.management.MBeanInfo)
   */
  protected MBeanInfo getCachedMBeanInfo()
  {
    return info;
  }
  /**
   * Returns the class name that will be used in the {@link MBeanInfo}
   * instance.  This is a customization hook, so that subclasses can
   * provide a custom class name.  By default, this returns the class
   * name from the supplied {@link MBeanInfo} instance.
   *
   * @param info the {@link MBeanInfo} instance constructed via
   *             reflection.
   * @return the class name to use in the instance.
   */
  protected String getClassName(MBeanInfo info)
  {
    return info.getClassName();
  }
  /**
   * Returns information on the constructors that will be used in
   * the {@link MBeanInfo} instance.  This is a customization hook,
   * so that subclasses can provide their own information on the
   * bean's constructors, if necessary.  By default, this method
   * returns null unless the implementation supplied
   * is either null or this.  This default
   * implementation prevents the use of
   * {@link MBeanServer#createMBean} in cases where the bean is
   * not created as a subclass of {@link StandardMBean}.
   *
   * @param constructors the constructor information created via
   *                     reflection.
   * @param impl the implementation, or null if this
   *             should be ignored.
   * @return the constructor information to use.
   */
  protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[]
                                                   constructors, Object impl)
  {
    if (impl == null || impl == this)
      return constructors;
    return null;
  }
  /**
   * Returns the description of the attribute that will be used in
   * the supplied {@link MBeanAttributeInfo} instance.  This is a
   * customization hook, so that subclasses can provide a custom
   * description.  By default, this calls
   * {@link #getDescription(MBeanFeatureInfo)} with the supplied
   * {@link MBeanAttributeInfo} instance.
   *
   * @param info the {@link MBeanAttributeInfo} instance constructed
   *             via reflection.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanAttributeInfo info)
  {
    return getDescription((MBeanFeatureInfo) info);
  }
  /**
   * Returns the description of the constructor that will be used in
   * the supplied {@link MBeanConstructorInfo} instance.  This is a
   * customization hook, so that subclasses can provide a custom
   * description.  By default, this calls
   * {@link #getDescription(MBeanFeatureInfo)} with the supplied
   * {@link MBeanConstructorInfo} instance.
   *
   * @param info the {@link MBeanConstructorInfo} instance constructed
   *             via reflection.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanConstructorInfo info)
  {
    return getDescription((MBeanFeatureInfo) info);
  }
  /**
   * Returns the description of the nth parameter of the constructor
   * that will be used in the supplied {@link MBeanParameterInfo}
   * instance.  This is a customization hook, so that subclasses
   * can provide a custom description.  By default, this calls
   * param.getDescription().
   *
   * @param info the {@link MBeanConstructorInfo} instance constructed
   *             via reflection.
   * @param param the {@link MBeanParameterInfo} instance constructed
   *             via reflection.
   * @param n the number of the parameter, in order to link it to the
   *          information on the constructor.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanConstructorInfo info,
                                  MBeanParameterInfo param, int n)
  {
    return param.getDescription();
  }
  /**
   * Returns the description of the supplied feature that
   * will be used in the supplied {@link MBeanFeatureInfo}
   * instance.  This is a customization hook, so that subclasses
   * can provide a custom description.  By default, this calls
   * info.getDescription().  This method is also called
   * by default for the more specific description methods for attributes,
   * constructors and operations.
   *
   * @param info the {@link MBeanFeatureInfo} instance constructed
   *             via reflection.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanFeatureInfo info)
  {
    return info.getDescription();
  }
  /**
   * Returns the description of the bean that will be used in the
   * supplied {@link MBeanInfo} instance.  This is a customization
   * hook, so that subclasses can provide a custom description.  By
   * default, this calls info.getDescription().
   *
   * @param info the {@link MBeanInfo} instance constructed
   *             via reflection.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanInfo info)
  {
    return info.getDescription();
  }
  /**
   * Returns the description of the operation that will be used in
   * the supplied {@link MBeanOperationInfo} instance.  This is a
   * customization hook, so that subclasses can provide a custom
   * description.  By default, this calls
   * {@link #getDescription(MBeanFeatureInfo)} with the supplied
   * {@link MBeanOperationInfo} instance.
   *
   * @param info the {@link MBeanOperationInfo} instance constructed
   *             via reflection.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanOperationInfo info)
  {
    return getDescription((MBeanFeatureInfo) info);
  }
  /**
   * Returns the description of the nth parameter of the operation
   * that will be used in the supplied {@link MBeanParameterInfo}
   * instance.  This is a customization hook, so that subclasses
   * can provide a custom description.  By default, this calls
   * param.getDescription().
   *
   * @param info the {@link MBeanOperationInfo} instance constructed
   *             via reflection.
   * @param param the {@link MBeanParameterInfo} instance constructed
   *             via reflection.
   * @param n the number of the parameter, in order to link it to the
   *          information on the operation.
   * @return the description to use in the instance.
   */
  protected String getDescription(MBeanOperationInfo info,
                                  MBeanParameterInfo param, int n)
  {
    return param.getDescription();
  }
  /**
   * Returns the impact of the operation that will be used in the
   * supplied {@link MBeanOperationInfo} instance.  This is a
   * customization hook, so that subclasses can provide a custom
   * impact flag.  By default, this returns
   * info.getImpact().
   *
   * @param info the {@link MBeanOperationInfo} instance constructed
   *             via reflection.
   * @return the impact flag to use in the instance.
   */
  protected int getImpact(MBeanOperationInfo info)
  {
    return info.getImpact();
  }
  /**
   * Returns the instance that implements this bean.
   *
   * @return the implementation.
   */
  public Object getImplementation()
  {
    return impl;
  }
  /**
   * Returns the class of the instance that implements this bean.
   *
   * @return the implementation class.
   */
  public Class> getImplementationClass()
  {
    return impl.getClass();
  }
  /**
   * * Returns an information object which lists the attributes * and actions associated with the management bean. This * implementation proceeds as follows: *
*param.getName().
   *
   * @param info the {@link MBeanConstructorInfo} instance constructed
   *             via reflection.
   * @param param the {@link MBeanParameterInfo} instance constructed
   *             via reflection.
   * @param n the number of the parameter, in order to link it to the
   *          information on the constructor.
   * @return the name to use in the instance.
   */
  protected String getParameterName(MBeanConstructorInfo info,
                                    MBeanParameterInfo param, int n)
  {
    return param.getName();
  }
  /**
   * Returns the name of the nth parameter of the operation
   * that will be used in the supplied {@link MBeanParameterInfo}
   * instance.  This is a customization hook, so that subclasses
   * can provide a custom name.  By default, this calls
   * param.getName().
   *
   * @param info the {@link MBeanOperationInfo} instance constructed
   *             via reflection.
   * @param param the {@link MBeanParameterInfo} instance constructed
   *             via reflection.
   * @param n the number of the parameter, in order to link it to the
   *          information on the operation.
   * @return the name to use in the instance.
   */
  protected String getParameterName(MBeanOperationInfo info,
                                    MBeanParameterInfo param, int n)
  {
    return param.getName();
  }
  /**
   * Invokes the specified action on the management bean using
   * the supplied parameters.  The signature of the action is
   * specified by a {@link String} array, which lists the classes
   * corresponding to each parameter.  The class loader used to
   * load these classes is the same as that used for loading the
   * management bean itself.
   *
   * @param name the name of the action to invoke.
   * @param params the parameters used to call the action.
   * @param signature the signature of the action.
   * @return the return value of the action.
   * @throws MBeanException if the action throws an exception.  The
   *                        thrown exception is the cause of this
   *                        exception.
   * @throws ReflectionException if an exception occurred in trying
   *                             to use the reflection interface
   *                             to invoke the action.  The
   *                             thrown exception is the cause of
   *                             this exception.
   */
  public Object invoke(String name, Object[] params, String[] signature)
    throws MBeanException, ReflectionException
  {
    if (name.startsWith("get") || name.startsWith("is") ||
        name.startsWith("set"))
      throw new ReflectionException(new NoSuchMethodException(),
                                    "Invocation of an attribute " +
                                    "method is disallowed.");
    ClassLoader loader = getClass().getClassLoader();
    Class>[] sigTypes;
    if (signature != null)
      {
        sigTypes = new Class>[signature.length];
        for (int a = 0; a < signature.length; ++a)
          try
            {
              sigTypes[a] = Class.forName(signature[a], true, loader);
            }
          catch (ClassNotFoundException e)
            {
              throw new ReflectionException(e, "The class, " + signature[a] +
                                            ", in the method signature " +
                                            "could not be loaded.");
            }
      }
    else
      sigTypes = null;
    Method method;
    try
      {
        method = iface.getMethod(name, sigTypes);
      }
    catch (NoSuchMethodException e)
      {
        throw new ReflectionException(e, "The method, " + name +
                                      ", could not be found.");
      }
    Object result;
    try
      {
        result = method.invoke(impl, params);
      }
    catch (IllegalAccessException e)
      {
        throw new ReflectionException(e, "Failed to call " + name);
      }
    catch (IllegalArgumentException e)
      {
        throw new ReflectionException(e, "Failed to call " + name);
      }
    catch (InvocationTargetException e)
      {
        throw new MBeanException((Exception) e.getCause(), "The method "
                                 + name + " threw an exception");
      }
    return result;
  }
  /**
   * Sets the value of the specified attribute of the
   * management bean.  The management bean should perform
   * a lookup for the named attribute, and sets its value
   * using the associated setter method, if possible.
   *
   * @param attribute the attribute to set.
   * @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.
   * @see #getAttribute(String)
   */
  public void setAttribute(Attribute attribute)
    throws AttributeNotFoundException, InvalidAttributeValueException,
           MBeanException, ReflectionException
  {
    String name = attribute.getName();
    String attName = name.substring(0, 1).toUpperCase() + name.substring(1);
    Object val = attribute.getValue();
    try
      {
        getMutator(attName, val.getClass()).invoke(impl, new Object[] { val });
      }
    catch (IllegalAccessException e)
      {
        throw new ReflectionException(e, "Failed to set " + name);
      }
    catch (IllegalArgumentException e)
      {
        throw ((InvalidAttributeValueException)
               new InvalidAttributeValueException(attribute.getValue() +
                                                  " is an invalid value for " +
                                                  name).initCause(e));
      }
    catch (InvocationTargetException e)
      {
        throw new MBeanException(e, "The getter of " + name +
                                 " threw an exception");
      }
  }
  /**
   * Sets the value of each of the specified attributes
   * to that supplied by the {@link Attribute} object.
   * The returned list contains the attributes that were
   * set and their new values.
   *
   * @param attributes the attributes to set.
   * @return a list of the changed attributes.
   * @see #getAttributes(AttributeList)
   */
  public AttributeList setAttributes(AttributeList attributes)
  {
    AttributeList list = new AttributeList(attributes.size());
    Iterator