javax.management.StandardMBean Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) The MX4J Contributors.
* All rights reserved.
*
* This software is distributed under the terms of the MX4J License version 1.0.
* See the terms of the MX4J License in the documentation provided with this software.
*/
package javax.management;
import mx4j.AbstractDynamicMBean;
import mx4j.server.MBeanIntrospector;
import mx4j.server.MBeanMetaData;
/**
* StandardMBean eases the development of MBeans that have a management interface described
* by a java interface, like plain standard MBeans have; differently from a plain standard
* MBean, StandardMBean is not tied to the JMX lexical patterns and allows more control on the
* customization of the MBeanInfo that describes the MBean (for example it allows to describe
* metadata descriptions).
* Usage of StandardMBean with a management interface that does not follow the JMX lexical patterns:
*
* public interface Management
* {
* ...
* }
*
* public class Service implements Management
* {
* ...
* }
*
* Service service = new Service();
* StandardMBean mbean = new StandardMBean(service, Management.class);
* MBeanServer server = ...;
* ObjectName name = ...;
* server.registerMBean(mbean, name);
*
* Usage of a subclass of StandardMBean:
*
* public interface Management
* {
* ...
* }
*
* public class Service extends StandardMBean implements Management
* {
* public Service()
* {
* super(Manegement.class);
* }
* ...
* }
*
* Service mbean = new Service();
* MBeanServer server = ...;
* ObjectName name = ...;
* server.registerMBean(mbean, name);
*
* Usage of StandardMBean with a management interface that follows the JMX lexical patterns
* (this is similar to plain standard MBeans):
*
* public interface ServiceMBean
* {
* ...
* }
*
* public class Service implements ServiceMBean
* {
* ...
* }
*
* Service service = new Service();
* StandardMBean mbean = new StandardMBean(service, null);
* MBeanServer server = ...;
* ObjectName name = ...;
* server.registerMBean(mbean, name);
*
*
* @version $Revision: 1.5 $
* @since JMX 1.2
*/
public class StandardMBean implements DynamicMBean
{
private MBeanMetaData metadata;
private MBeanInfo info;
private DynamicMBean support;
/**
* Creates a new StandardMBean.
*
* @param implementation The MBean implementation for this StandardMBean
* @param management The management interface; if null, the JMX lexical patterns will be used
* @throws IllegalArgumentException If implementation
is null
* @throws NotCompliantMBeanException If implementation
does not implement managementInterface
,
* or if the management interface is not a valid JMX Management Interface
* @see #setImplementation
*/
public StandardMBean(Object implementation, Class management) throws NotCompliantMBeanException
{
this(implementation, management, false);
}
/**
* Creates a new StandardMBean using 'this' as implementation.
*
* @see #StandardMBean(Object,Class)
*/
protected StandardMBean(Class managementInterface) throws NotCompliantMBeanException
{
this(null, managementInterface, true);
}
private StandardMBean(Object implementation, Class management, boolean useThis) throws NotCompliantMBeanException
{
if (useThis) implementation = this;
if (implementation == null) throw new IllegalArgumentException("Implementation cannot be null");
if (management != null && !management.isInterface()) throw new NotCompliantMBeanException("Class " + management + " is not an interface");
metadata = introspectMBean(implementation, management);
if (metadata == null) throw new NotCompliantMBeanException("StandardMBean is not compliant");
support = new StandardMBeanSupport();
}
/**
* Sets the MBean implementation for this StandardMBean.
*
* @param implementation The MBean implementation for this StandardMBean
* @throws IllegalArgumentException If implementation
is null
* @throws NotCompliantMBeanException If implementation
does not implement the management interface
* returned by {@link #getMBeanInterface}
* @see #StandardMBean(Object,Class)
*/
public void setImplementation(Object implementation) throws NotCompliantMBeanException
{
if (implementation == null) throw new IllegalArgumentException("Implementation cannot be null");
Class management = getMBeanInterface();
if (!management.isInstance(implementation)) throw new NotCompliantMBeanException("Implementation " + implementation + " does not implement interface " + management);
metadata.setMBean(implementation);
}
/**
* Returns the implementation supplied to this StandardMBean, or this object if no implementation was supplied
*
* @see #StandardMBean(Object,Class)
* @see #setImplementation
*/
public Object getImplementation()
{
return metadata.getMBean();
}
/**
* Returns the management interface for this MBean. This interface is set at creation time and cannot be changed
* even if the implementation object can be changed (but it must implement the same interface).
*
* @see #StandardMBean(Object,Class)}
* @see #setImplementation
*/
public final Class getMBeanInterface()
{
return metadata.getMBeanInterface();
}
/**
* Returns the class of the MBean implementation for this StandardMBean, or 'this' (sub)class if no
* implementation was supplied.
*
* @see #StandardMBean(Object,Class)}
*/
public Class getImplementationClass()
{
return metadata.getMBean().getClass();
}
public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException
{
return support.getAttribute(attribute);
}
public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
{
support.setAttribute(attribute);
}
public AttributeList getAttributes(String[] attributes)
{
return support.getAttributes(attributes);
}
public AttributeList setAttributes(AttributeList attributes)
{
return support.setAttributes(attributes);
}
public Object invoke(String method, Object[] arguments, String[] params) throws MBeanException, ReflectionException
{
return support.invoke(method, arguments, params);
}
/**
* See {@link DynamicMBean#getMBeanInfo}.
* By default, the metadata is cached the first time is created; if the caching has been disabled,
* the metadata is created from scratch each time.
*
* @see #getCachedMBeanInfo
* @see #cacheMBeanInfo
*/
public MBeanInfo getMBeanInfo()
{
MBeanInfo info = getCachedMBeanInfo();
if (info == null)
{
info = setupMBeanInfo(metadata.getMBeanInfo());
cacheMBeanInfo(info);
}
return info;
}
/**
* Returns the class name of this MBean.
* By default returns {@link MBeanInfo#getClassName info.getClassName()}
*/
protected String getClassName(MBeanInfo info)
{
return info == null ? null : info.getClassName();
}
/**
* Returns the description for this MBean.
* By default returns {@link MBeanInfo#getDescription info.getDescription()}
*/
protected String getDescription(MBeanInfo info)
{
return info == null ? null : info.getDescription();
}
/**
* Returns the description for the given feature.
* By default returns {@link MBeanFeatureInfo#getDescription info.getDescription()}
*
* @see #getDescription(MBeanAttributeInfo)
* @see #getDescription(MBeanConstructorInfo)
* @see #getDescription(MBeanOperationInfo)
*/
protected String getDescription(MBeanFeatureInfo info)
{
return info == null ? null : info.getDescription();
}
/**
* Returns the description for the given attribute.
* By default calls {@link #getDescription(MBeanFeatureInfo)}
*/
protected String getDescription(MBeanAttributeInfo info)
{
return getDescription((MBeanFeatureInfo)info);
}
/**
* Returns the description for the given constructor.
* By default calls {@link #getDescription(MBeanFeatureInfo)}
*/
protected String getDescription(MBeanConstructorInfo info)
{
return getDescription((MBeanFeatureInfo)info);
}
/**
* Returns the description for the given operation.
* By default calls {@link #getDescription(MBeanFeatureInfo)}
*/
protected String getDescription(MBeanOperationInfo info)
{
return getDescription((MBeanFeatureInfo)info);
}
/**
* Returns the description of the (sequence + 1)th parameter (that is: if sequence is 0 returns the description of the first
* parameter, if sequence is 1 returns the description of the second parameter, and so on) for the given constructor.
* By default returns {@link MBeanParameterInfo#getDescription param.getDescription()}.
*/
protected String getDescription(MBeanConstructorInfo constructor, MBeanParameterInfo param, int sequence)
{
return param == null ? null : param.getDescription();
}
/**
* Returns the description of the (sequence + 1)th parameter (that is: if sequence is 0 returns the description of the first
* parameter, if sequence is 1 returns the description of the second parameter, and so on) for the given operation.
* By default returns {@link MBeanParameterInfo#getDescription param.getDescription()}.
*/
protected String getDescription(MBeanOperationInfo operation, MBeanParameterInfo param, int sequence)
{
return param == null ? null : param.getDescription();
}
/**
* Returns the name of the (sequence + 1)th parameter (that is: if sequence is 0 returns the name of the first
* parameter, if sequence is 1 returns the name of the second parameter, and so on) for the given constructor.
* By default returns {@link MBeanParameterInfo#getName param.getName()}.
*/
protected String getParameterName(MBeanConstructorInfo constructor, MBeanParameterInfo param, int sequence)
{
return param == null ? null : param.getName();
}
/**
* Returns the name of the (sequence + 1)th parameter (that is: if sequence is 0 returns the name of the first
* parameter, if sequence is 1 returns the name of the second parameter, and so on) for the given operation.
* By default returns {@link MBeanParameterInfo#getName param.getName()}.
*/
protected String getParameterName(MBeanOperationInfo operation, MBeanParameterInfo param, int sequence)
{
return param == null ? null : param.getName();
}
/**
* Returns the impact flag for the given MBeanOperationInfo.
* By default returns {@link MBeanOperationInfo#getImpact info.getImpact()}
*/
protected int getImpact(MBeanOperationInfo info)
{
return info == null ? MBeanOperationInfo.UNKNOWN : info.getImpact();
}
/**
* Returns, by default, the given constructors
if implementation
* is 'this' object or null, otherwise returns null.
* Since the MBean that is registered in an MBeanServer is always an instance of StandardMBean,
* there is no meaning in providing MBeanConstructorInfo if the implementation passed to
* {@link #StandardMBean(Object,Class)} is not 'this' object.
*/
protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[] constructors, Object implementation)
{
if (implementation == this || implementation == null) return constructors;
return null;
}
/**
* Returns the cached MBeanInfo, or null if the MBeanInfo is not cached.
*
* @see #cacheMBeanInfo
* @see #getMBeanInfo
*/
protected MBeanInfo getCachedMBeanInfo()
{
return info;
}
/**
* Caches the given MBeanInfo after it has been created, by introspection, with the information
* provided to constructors.
* Override to disable caching, or to install different caching policies.
*
* @param info The MBeanInfo to cache; if it is null, the cache is cleared.
* @see #getCachedMBeanInfo
* @see #getMBeanInfo
*/
protected void cacheMBeanInfo(MBeanInfo info)
{
this.info = info;
}
/**
* This method calls the callbacks provided by this class that allow the user to customize the MBeanInfo
*
* @param info The MBeanInfo as it was introspected
*/
private MBeanInfo setupMBeanInfo(MBeanInfo info)
{
String clsName = getClassName(info);
String description = getDescription(info);
MBeanConstructorInfo[] ctors = setupConstructors(info.getConstructors());
MBeanAttributeInfo[] attrs = setupAttributes(info.getAttributes());
MBeanOperationInfo[] opers = setupOperations(info.getOperations());
MBeanNotificationInfo[] notifs = setupNotifications(info.getNotifications());
return new MBeanInfo(clsName, description, attrs, ctors, opers, notifs);
}
private MBeanConstructorInfo[] setupConstructors(MBeanConstructorInfo[] originalCtors)
{
MBeanConstructorInfo[] ctors = getConstructors(originalCtors, getImplementation());
if (ctors == null) return null;
MBeanConstructorInfo[] newCtors = new MBeanConstructorInfo[ctors.length];
for (int i = 0; i < ctors.length; ++i)
{
MBeanConstructorInfo ctor = ctors[i];
if (ctor == null) continue;
MBeanParameterInfo[] newParams = null;
MBeanParameterInfo[] params = ctor.getSignature();
if (params != null)
{
newParams = new MBeanParameterInfo[params.length];
for (int j = 0; j < params.length; ++j)
{
MBeanParameterInfo param = params[j];
if (param == null) continue;
String paramName = getParameterName(ctor, param, j);
String paramDescr = getDescription(ctor, param, j);
newParams[j] = new MBeanParameterInfo(paramName, param.getType(), paramDescr);
}
}
String ctorDescr = getDescription(ctor);
newCtors[i] = new MBeanConstructorInfo(ctor.getName(), ctorDescr, newParams);
}
return newCtors;
}
private MBeanAttributeInfo[] setupAttributes(MBeanAttributeInfo[] attrs)
{
if (attrs == null) return null;
MBeanAttributeInfo[] newAttrs = new MBeanAttributeInfo[attrs.length];
for (int i = 0; i < attrs.length; ++i)
{
MBeanAttributeInfo attr = attrs[i];
if (attr == null) continue;
String attrDescr = getDescription(attr);
newAttrs[i] = new MBeanAttributeInfo(attr.getName(), attr.getType(), attrDescr, attr.isReadable(), attr.isWritable(), attr.isIs());
}
return newAttrs;
}
private MBeanOperationInfo[] setupOperations(MBeanOperationInfo[] opers)
{
if (opers == null) return null;
MBeanOperationInfo[] newOpers = new MBeanOperationInfo[opers.length];
for (int i = 0; i < opers.length; ++i)
{
MBeanOperationInfo oper = opers[i];
if (oper == null) continue;
MBeanParameterInfo[] newParams = null;
MBeanParameterInfo[] params = oper.getSignature();
if (params != null)
{
newParams = new MBeanParameterInfo[params.length];
for (int j = 0; j < params.length; ++j)
{
MBeanParameterInfo param = params[j];
if (param == null) continue;
String paramName = getParameterName(oper, param, j);
String paramDescr = getDescription(oper, param, j);
newParams[j] = new MBeanParameterInfo(paramName, param.getType(), paramDescr);
}
}
String operDescr = getDescription(oper);
int operImpact = getImpact(oper);
newOpers[i] = new MBeanOperationInfo(oper.getName(), operDescr, newParams, oper.getReturnType(), operImpact);
}
return newOpers;
}
private MBeanNotificationInfo[] setupNotifications(MBeanNotificationInfo[] notifs)
{
return notifs == null ? null : notifs;
}
private MBeanMetaData introspectMBean(Object implementation, Class management)
{
MBeanMetaData metadata = MBeanMetaData.Factory.create();
metadata.setMBean(implementation);
metadata.setClassLoader(implementation.getClass().getClassLoader());
metadata.setMBeanStandard(true);
metadata.setMBeanInterface(management);
MBeanIntrospector introspector = new MBeanIntrospector();
introspector.introspect(metadata);
if (!introspector.isMBeanCompliant(metadata)) return null;
return metadata;
}
private class StandardMBeanSupport extends AbstractDynamicMBean
{
public synchronized MBeanInfo getMBeanInfo()
{
return StandardMBean.this.getMBeanInfo();
}
protected Object getResource()
{
return StandardMBean.this.getImplementation();
}
}
}