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