/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jmx.export.assembler;
import javax.management.Descriptor;
import javax.management.JMException;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanConstructorInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanNotificationInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import org.springframework.aop.support.AopUtils;
import org.springframework.jmx.support.JmxUtils;
/**
* Abstract implementation of the <code>MBeanInfoAssembler</code> interface
* that encapsulates the creation of a <code>ModelMBeanInfo</code> instance
* but delegates the creation of metadata to subclasses.
*
* <p>This class offers two flavors of Class extraction from a managed bean
* instance: {@link #getTargetClass}, extracting the target class behind
* any kind of AOP proxy, and {@link #getClassToExpose}, returning the
* class or interface that will be searched for annotations and exposed
* to the JMX runtime.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.2
*/
public abstract class AbstractMBeanInfoAssembler implements MBeanInfoAssembler {
/**
* Create an instance of the <code>ModelMBeanInfoSupport</code> class supplied with all
* JMX implementations and populates the metadata through calls to the subclass.
* @param managedBean the bean that will be exposed (might be an AOP proxy)
* @param beanKey the key associated with the managed bean
* @return the populated ModelMBeanInfo instance
* @throws JMException in case of errors
* @see #getDescription(Object, String)
* @see #getAttributeInfo(Object, String)
* @see #getConstructorInfo(Object, String)
* @see #getOperationInfo(Object, String)
* @see #getNotificationInfo(Object, String)
* @see #populateMBeanDescriptor(javax.management.Descriptor, Object, String)
*/
public ModelMBeanInfo getMBeanInfo(Object managedBean, String beanKey) throws JMException {
checkManagedBean(managedBean);
ModelMBeanInfo info = new ModelMBeanInfoSupport(
getClassName(managedBean, beanKey), getDescription(managedBean, beanKey),
getAttributeInfo(managedBean, beanKey), getConstructorInfo(managedBean, beanKey),
getOperationInfo(managedBean, beanKey), getNotificationInfo(managedBean, beanKey));
Descriptor desc = info.getMBeanDescriptor();
populateMBeanDescriptor(desc, managedBean, beanKey);
info.setMBeanDescriptor(desc);
return info;
}
/**
* Check the given bean instance, throwing an IllegalArgumentException
* if it is not eligible for exposure with this assembler.
* <p>Default implementation is empty, accepting every bean instance.
* @param managedBean the bean that will be exposed (might be an AOP proxy)
* @throws IllegalArgumentException the bean is not valid for exposure
*/
protected void checkManagedBean(Object managedBean) throws IllegalArgumentException {
}
/**
* Return the actual bean class of the given bean instance.
* This is the class exposed to description-style JMX properties.
* <p>Default implementation returns the target class for an AOP proxy,
* and the plain bean class else.
* @param managedBean the bean instance (might be an AOP proxy)
* @return the bean class to expose
* @see org.springframework.aop.framework.AopProxyUtils#getTargetClass
*/
protected Class getTargetClass(Object managedBean) {
return AopUtils.getTargetClass(managedBean);
}
/**
* Return the class or interface to expose for the given bean.
* This is the class that will be searched for attributes and operations
* (for example, checked for annotations).
* @param managedBean the bean instance (might be an AOP proxy)
* @return the bean class to expose
* @see JmxUtils#getClassToExpose(Object)
*/
protected Class<?> getClassToExpose(Object managedBean) {
return JmxUtils.getClassToExpose(managedBean);
}
/**
* Return the class or interface to expose for the given bean class.
* This is the class that will be searched for attributes and operations
* @param beanClass the bean class (might be an AOP proxy class)
* @return the bean class to expose
* @see JmxUtils#getClassToExpose(Class)
*/
protected Class<?> getClassToExpose(Class<?> beanClass) {
return JmxUtils.getClassToExpose(beanClass);
}
/**
* Get the class name of the MBean resource.
* <p>Default implementation returns a simple description for the MBean
* based on the class name.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @return the MBean description
* @throws JMException in case of errors
*/
protected String getClassName(Object managedBean, String beanKey) throws JMException {
return getTargetClass(managedBean).getName();
}
/**
* Get the description of the MBean resource.
* <p>Default implementation returns a simple description for the MBean
* based on the class name.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @throws JMException in case of errors
*/
protected String getDescription(Object managedBean, String beanKey) throws JMException {
String targetClassName = getTargetClass(managedBean).getName();
if (AopUtils.isAopProxy(managedBean)) {
return "Proxy for " + targetClassName;
}
return targetClassName;
}
/**
* Called after the <code>ModelMBeanInfo</code> instance has been constructed but
* before it is passed to the <code>MBeanExporter</code>.
* <p>Subclasses can implement this method to add additional descriptors to the
* MBean metadata. Default implementation is empty.
* @param descriptor the <code>Descriptor</code> for the MBean resource.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @throws JMException in case of errors
*/
protected void populateMBeanDescriptor(Descriptor descriptor, Object managedBean, String beanKey)
throws JMException {
}
/**
* Get the constructor metadata for the MBean resource. Subclasses should implement
* this method to return the appropriate metadata for all constructors that should
* be exposed in the management interface for the managed resource.
* <p>Default implementation returns an empty array of <code>ModelMBeanConstructorInfo</code>.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @return the constructor metadata
* @throws JMException in case of errors
*/
protected ModelMBeanConstructorInfo[] getConstructorInfo(Object managedBean, String beanKey)
throws JMException {
return new ModelMBeanConstructorInfo[0];
}
/**
* Get the notification metadata for the MBean resource. Subclasses should implement
* this method to return the appropriate metadata for all notifications that should
* be exposed in the management interface for the managed resource.
* <p>Default implementation returns an empty array of <code>ModelMBeanNotificationInfo</code>.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @return the notification metadata
* @throws JMException in case of errors
*/
protected ModelMBeanNotificationInfo[] getNotificationInfo(Object managedBean, String beanKey)
throws JMException {
return new ModelMBeanNotificationInfo[0];
}
/**
* Get the attribute metadata for the MBean resource. Subclasses should implement
* this method to return the appropriate metadata for all the attributes that should
* be exposed in the management interface for the managed resource.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @return the attribute metadata
* @throws JMException in case of errors
*/
protected abstract ModelMBeanAttributeInfo[] getAttributeInfo(Object managedBean, String beanKey)
throws JMException;
/**
* Get the operation metadata for the MBean resource. Subclasses should implement
* this method to return the appropriate metadata for all operations that should
* be exposed in the management interface for the managed resource.
* @param managedBean the bean instance (might be an AOP proxy)
* @param beanKey the key associated with the MBean in the beans map
* of the <code>MBeanExporter</code>
* @return the operation metadata
* @throws JMException in case of errors
*/
protected abstract ModelMBeanOperationInfo[] getOperationInfo(Object managedBean, String beanKey)
throws JMException;
}
|