/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package javax.management;
import org.jboss.mx.logging.Logger;
import org.jboss.mx.logging.SystemLogger;
import org.jboss.mx.metadata.StandardMetaData;
/**
* A helper class to allow standard mbeans greater control over their
* management interface.<p>
*
* Extending this class actually makes the mbean a dynamic mbean, but
* with the convenience of a standard mbean.
*
* @todo make this more dynamic, somehow delegate to an XMBean?
* @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>.
* @version $Revision: 1.1 $
*/
public class StandardMBean
implements DynamicMBean
{
// Constants ---------------------------------------------------
Logger log = SystemLogger.getLogger(StandardMBean.class);
// Attributes --------------------------------------------------
/**
* The implementation object
*/
private Object implementation;
/**
* The management interface
*/
private Class mbeanInterface;
/**
* The cached mbeaninfo
*/
private MBeanInfo cachedMBeanInfo;
// Static -----------------------------------------------------
// Constructors ------------------------------------------------
/**
* Construct a DynamicMBean from the given implementation object
* and the passed management interface class.
*
* @param implementation the object implementing the mbean
* @param mbeanInterface the management interface of the mbean
* @exception IllegalArgumentException for a null implementation
* @exception NotCompliantMBeanException if the management interface
* does not follow the JMX design patterns or the implementation
* does not implement the interface
*/
public StandardMBean(Object implementation, Class mbeanInterface)
throws NotCompliantMBeanException
{
if (implementation == null)
throw new IllegalArgumentException("Null implementation");
init(implementation, mbeanInterface);
}
/**
* Construct a DynamicMBean from this object
* and the passed management interface class.<p>
*
* Used in subclassing
*
* @param mbeanInterface the management interface of the mbean
* @exception NotCompliantMBeanException if the management interface
* does not follow the JMX design patterns or this
* does not implement the interface
*/
protected StandardMBean(Class mbeanInterface)
throws NotCompliantMBeanException
{
init(this, mbeanInterface);
}
// Public ------------------------------------------------------
/**
* Retrieve the implementation object
*
* @return the implementation
*/
public Object getImplementation()
{
return implementation;
}
/**
* Replace the implementation object
*
* @todo make this work after the mbean is registered
* @param implementation the new implementation
* @exception IllegalArgumentException for a null parameter
* @exception NotCompliantMBeanException if the new implementation
* does not implement the interface supplied at
* construction
*/
public void setImplementation(Object implementation)
{
if (implementation == null)
throw new IllegalArgumentException("Null implementation");
this.implementation = implementation;
}
/**
* Retrieve the implementation class
*
* @return the class of the implementation
*/
public Class getImplementationClass()
{
return implementation.getClass();
}
/**
* Retrieve the management interface
*
* @return the management interface
*/
public Class getMBeanInterface()
{
return mbeanInterface;
}
// DynamicMBean Implementation ---------------------------------
public Object getAttribute(String attribute)
throws AttributeNotFoundException,
MBeanException, ReflectionException
{
throw new IllegalStateException("Do not invoke directly");
}
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException,
InvalidAttributeValueException,
MBeanException, ReflectionException
{
throw new IllegalStateException("Do not invoke directly");
}
public AttributeList getAttributes(String[] attributes)
{
throw new IllegalStateException("Do not invoke directly");
}
public AttributeList setAttributes(AttributeList attributes)
{
throw new IllegalStateException("Do not invoke directly");
}
public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException
{
throw new IllegalStateException("Do not invoke directly");
}
public MBeanInfo getMBeanInfo()
{
MBeanInfo info = getCachedMBeanInfo();
if (info == null)
{
try
{
info = buildMBeanInfo(implementation, mbeanInterface);
}
catch (NotCompliantMBeanException e)
{
log.error("Unexcepted exception", e);
throw new IllegalStateException("Unexcepted exception " + e.toString());
}
}
return info;
}
// Y overrides -------------------------------------------------
// Protected ---------------------------------------------------
/**
* Retrieve the class name of the mbean
*
* @param info the default mbeaninfo derived by reflection
* @return the class name
*/
protected String getClassName(MBeanInfo info)
{
return info.getClassName();
}
/**
* Retrieve the description of the mbean
*
* @param info the default mbeaninfo derived by reflection
* @return the description
*/
protected String getDescription(MBeanInfo info)
{
return info.getDescription();
}
/**
* Retrieve the description of the mbean feature
*
* @param info the default mbeanfeatureinfo derived by reflection
* @return the description
*/
protected String getDescription(MBeanFeatureInfo info)
{
return info.getDescription();
}
/**
* Retrieve the description of the mbean attribute
*
* @param info the default mbeanattributeinfo derived by reflection
* @return the description
*/
protected String getDescription(MBeanAttributeInfo info)
{
return getDescription((MBeanFeatureInfo) info);
}
/**
* Retrieve the description of the mbean constructor
*
* @param info the default mbeanconstructorinfo derived by reflection
* @return the description
*/
protected String getDescription(MBeanConstructorInfo info)
{
return getDescription((MBeanFeatureInfo) info);
}
/**
* Retrieve the description of the mbean operation
*
* @param info the default mbeanoperationinfo derived by reflection
* @return the description
*/
protected String getDescription(MBeanOperationInfo info)
{
return getDescription((MBeanFeatureInfo) info);
}
/**
* Retrieve the description of the mbean constructor parameter
*
* @param info the default mbeanconstructorinfo derived by reflection
* @param param the parameter information
* @param sequence the parameter index, starting with zero
* @return the description
*/
protected String getDescription(MBeanConstructorInfo info, MBeanParameterInfo param, int sequence)
{
return param.getDescription();
}
/**
* Retrieve the description of the mbean operation parameter
*
* @param info the default mbeanoperationinfo derived by reflection
* @param param the parameter information
* @param sequence the parameter index, starting with zero
* @return the description
*/
protected String getDescription(MBeanOperationInfo info, MBeanParameterInfo param, int sequence)
{
return param.getDescription();
}
/**
* Retrieve the parameter name for a constructor
*
* @param info the default mbeanconstructorinfo derived by reflection
* @param param the parameter information
* @param sequence the parameter index, starting with zero
* @return the parameter name
*/
protected String getParameterName(MBeanConstructorInfo info, MBeanParameterInfo param, int sequence)
{
return param.getName();
}
/**
* Retrieve the parameter name for an operation
*
* @param info the default mbeanoperationinfo derived by reflection
* @param param the parameter information
* @param sequence the parameter index, starting with zero
* @return the parameter name
*/
protected String getParameterName(MBeanOperationInfo info, MBeanParameterInfo param, int sequence)
{
return param.getName();
}
/**
* Retrieve the impact of the mbean operation
*
* @param info the default mbeanoperationinfo derived by reflection
* @return the impact
*/
protected int getImpact(MBeanOperationInfo info)
{
return info.getImpact();
}
/**
* Retrieve the constructors
*
* @param constructors the default constructors derived by reflection
* @param implementation the implementation
* @return the constructors if the implementation is this, otherwise null
*/
protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[] constructors, Object implementation)
{
if (implementation == this)
return constructors;
else
return null;
}
/**
* Retrieve the cached mbean info
*
* @return the cached mbean info
*/
protected MBeanInfo getCachedMBeanInfo()
{
return cachedMBeanInfo;
}
/**
* Sets the cached mbean info
*
* @todo make this work after the mbean is registered
* @param info the mbeaninfo to cache, can be null to erase the cache
*/
protected void cacheMBeanInfo(MBeanInfo info)
{
cachedMBeanInfo = info;
}
// Package Private ---------------------------------------------
// Private -----------------------------------------------------
private final void init(Object implementation, Class mbeanInterface)
throws NotCompliantMBeanException
{
MBeanInfo info = buildMBeanInfo(implementation, mbeanInterface);
cacheMBeanInfo(info);
this.implementation = implementation;
}
private final MBeanInfo buildMBeanInfo(Object implementation, Class mbeanInterface)
throws NotCompliantMBeanException
{
StandardMetaData metaData = new StandardMetaData(implementation, mbeanInterface);
this.mbeanInterface = metaData.getMBeanInterface();
MBeanInfo info = metaData.build();
String className = getClassName(info);
String mainDescription = getDescription(info);
MBeanAttributeInfo[] attributes = info.getAttributes();
MBeanConstructorInfo[] constructors = info.getConstructors();
MBeanOperationInfo[] operations = info.getOperations();
MBeanNotificationInfo[] notifications = info.getNotifications();
for (int i = 0; i < attributes.length; i++)
{
MBeanAttributeInfo attribute = attributes[i];
String description = getDescription(attribute);
attributes[i] = new MBeanAttributeInfo(attribute.getName(), attribute.getType(),
description, attribute.isReadable(),
attribute.isWritable(), attribute.isIs());
}
constructors = getConstructors(constructors, this);
for (int i = 0; i < constructors.length; i++)
{
MBeanConstructorInfo constructor = constructors[i];
MBeanParameterInfo[] parameters = constructor.getSignature();
for (int j = 0; j < parameters.length; j++)
{
MBeanParameterInfo param = parameters[j];
String description = getDescription(constructor, param, j);
String name = getParameterName(constructor, param, j);
parameters[j] = new MBeanParameterInfo(name, param.getType(), description);
}
String description = getDescription(constructor);
constructors[i] = new MBeanConstructorInfo(constructor.getName(), description, parameters);
}
for (int i = 0; i < operations.length; i++)
{
MBeanOperationInfo operation = operations[i];
MBeanParameterInfo[] parameters = operation.getSignature();
for (int j = 0; j < parameters.length; j++)
{
MBeanParameterInfo param = parameters[j];
String description = getDescription(operation, param, j);
String name = getParameterName(operation, param, j);
parameters[j] = new MBeanParameterInfo(name, param.getType(), description);
}
String description = getDescription(operation);
int impact = getImpact(operation);
operations[i] = new MBeanOperationInfo(operation.getName(), description, parameters,
operation.getReturnType(), impact);
}
info = new MBeanInfo(className, mainDescription, attributes, constructors, operations, notifications);
return info;
}
// Inner Classes -----------------------------------------------
}