001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jmx.export.assembler; 018 019import javax.management.Descriptor; 020import javax.management.JMException; 021import javax.management.modelmbean.ModelMBeanAttributeInfo; 022import javax.management.modelmbean.ModelMBeanConstructorInfo; 023import javax.management.modelmbean.ModelMBeanInfo; 024import javax.management.modelmbean.ModelMBeanInfoSupport; 025import javax.management.modelmbean.ModelMBeanNotificationInfo; 026import javax.management.modelmbean.ModelMBeanOperationInfo; 027 028import org.springframework.aop.support.AopUtils; 029import org.springframework.jmx.support.JmxUtils; 030 031/** 032 * Abstract implementation of the {@code MBeanInfoAssembler} interface 033 * that encapsulates the creation of a {@code ModelMBeanInfo} instance 034 * but delegates the creation of metadata to subclasses. 035 * 036 * <p>This class offers two flavors of Class extraction from a managed bean 037 * instance: {@link #getTargetClass}, extracting the target class behind 038 * any kind of AOP proxy, and {@link #getClassToExpose}, returning the 039 * class or interface that will be searched for annotations and exposed 040 * to the JMX runtime. 041 * 042 * @author Rob Harrop 043 * @author Juergen Hoeller 044 * @since 1.2 045 */ 046public abstract class AbstractMBeanInfoAssembler implements MBeanInfoAssembler { 047 048 /** 049 * Create an instance of the {@code ModelMBeanInfoSupport} class supplied with all 050 * JMX implementations and populates the metadata through calls to the subclass. 051 * @param managedBean the bean that will be exposed (might be an AOP proxy) 052 * @param beanKey the key associated with the managed bean 053 * @return the populated ModelMBeanInfo instance 054 * @throws JMException in case of errors 055 * @see #getDescription(Object, String) 056 * @see #getAttributeInfo(Object, String) 057 * @see #getConstructorInfo(Object, String) 058 * @see #getOperationInfo(Object, String) 059 * @see #getNotificationInfo(Object, String) 060 * @see #populateMBeanDescriptor(javax.management.Descriptor, Object, String) 061 */ 062 @Override 063 public ModelMBeanInfo getMBeanInfo(Object managedBean, String beanKey) throws JMException { 064 checkManagedBean(managedBean); 065 ModelMBeanInfo info = new ModelMBeanInfoSupport( 066 getClassName(managedBean, beanKey), getDescription(managedBean, beanKey), 067 getAttributeInfo(managedBean, beanKey), getConstructorInfo(managedBean, beanKey), 068 getOperationInfo(managedBean, beanKey), getNotificationInfo(managedBean, beanKey)); 069 Descriptor desc = info.getMBeanDescriptor(); 070 populateMBeanDescriptor(desc, managedBean, beanKey); 071 info.setMBeanDescriptor(desc); 072 return info; 073 } 074 075 /** 076 * Check the given bean instance, throwing an IllegalArgumentException 077 * if it is not eligible for exposure with this assembler. 078 * <p>Default implementation is empty, accepting every bean instance. 079 * @param managedBean the bean that will be exposed (might be an AOP proxy) 080 * @throws IllegalArgumentException the bean is not valid for exposure 081 */ 082 protected void checkManagedBean(Object managedBean) throws IllegalArgumentException { 083 } 084 085 /** 086 * Return the actual bean class of the given bean instance. 087 * This is the class exposed to description-style JMX properties. 088 * <p>Default implementation returns the target class for an AOP proxy, 089 * and the plain bean class else. 090 * @param managedBean the bean instance (might be an AOP proxy) 091 * @return the bean class to expose 092 * @see org.springframework.aop.support.AopUtils#getTargetClass(Object) 093 */ 094 protected Class<?> getTargetClass(Object managedBean) { 095 return AopUtils.getTargetClass(managedBean); 096 } 097 098 /** 099 * Return the class or interface to expose for the given bean. 100 * This is the class that will be searched for attributes and operations 101 * (for example, checked for annotations). 102 * @param managedBean the bean instance (might be an AOP proxy) 103 * @return the bean class to expose 104 * @see JmxUtils#getClassToExpose(Object) 105 */ 106 protected Class<?> getClassToExpose(Object managedBean) { 107 return JmxUtils.getClassToExpose(managedBean); 108 } 109 110 /** 111 * Return the class or interface to expose for the given bean class. 112 * This is the class that will be searched for attributes and operations 113 * @param beanClass the bean class (might be an AOP proxy class) 114 * @return the bean class to expose 115 * @see JmxUtils#getClassToExpose(Class) 116 */ 117 protected Class<?> getClassToExpose(Class<?> beanClass) { 118 return JmxUtils.getClassToExpose(beanClass); 119 } 120 121 /** 122 * Get the class name of the MBean resource. 123 * <p>Default implementation returns a simple description for the MBean 124 * based on the class name. 125 * @param managedBean the bean instance (might be an AOP proxy) 126 * @param beanKey the key associated with the MBean in the beans map 127 * of the {@code MBeanExporter} 128 * @return the MBean description 129 * @throws JMException in case of errors 130 */ 131 protected String getClassName(Object managedBean, String beanKey) throws JMException { 132 return getTargetClass(managedBean).getName(); 133 } 134 135 /** 136 * Get the description of the MBean resource. 137 * <p>Default implementation returns a simple description for the MBean 138 * based on the class name. 139 * @param managedBean the bean instance (might be an AOP proxy) 140 * @param beanKey the key associated with the MBean in the beans map 141 * of the {@code MBeanExporter} 142 * @throws JMException in case of errors 143 */ 144 protected String getDescription(Object managedBean, String beanKey) throws JMException { 145 String targetClassName = getTargetClass(managedBean).getName(); 146 if (AopUtils.isAopProxy(managedBean)) { 147 return "Proxy for " + targetClassName; 148 } 149 return targetClassName; 150 } 151 152 /** 153 * Called after the {@code ModelMBeanInfo} instance has been constructed but 154 * before it is passed to the {@code MBeanExporter}. 155 * <p>Subclasses can implement this method to add additional descriptors to the 156 * MBean metadata. Default implementation is empty. 157 * @param descriptor the {@code Descriptor} for the MBean resource. 158 * @param managedBean the bean instance (might be an AOP proxy) 159 * @param beanKey the key associated with the MBean in the beans map 160 * of the {@code MBeanExporter} 161 * @throws JMException in case of errors 162 */ 163 protected void populateMBeanDescriptor(Descriptor descriptor, Object managedBean, String beanKey) 164 throws JMException { 165 } 166 167 /** 168 * Get the constructor metadata for the MBean resource. Subclasses should implement 169 * this method to return the appropriate metadata for all constructors that should 170 * be exposed in the management interface for the managed resource. 171 * <p>Default implementation returns an empty array of {@code ModelMBeanConstructorInfo}. 172 * @param managedBean the bean instance (might be an AOP proxy) 173 * @param beanKey the key associated with the MBean in the beans map 174 * of the {@code MBeanExporter} 175 * @return the constructor metadata 176 * @throws JMException in case of errors 177 */ 178 protected ModelMBeanConstructorInfo[] getConstructorInfo(Object managedBean, String beanKey) 179 throws JMException { 180 return new ModelMBeanConstructorInfo[0]; 181 } 182 183 /** 184 * Get the notification metadata for the MBean resource. Subclasses should implement 185 * this method to return the appropriate metadata for all notifications that should 186 * be exposed in the management interface for the managed resource. 187 * <p>Default implementation returns an empty array of {@code ModelMBeanNotificationInfo}. 188 * @param managedBean the bean instance (might be an AOP proxy) 189 * @param beanKey the key associated with the MBean in the beans map 190 * of the {@code MBeanExporter} 191 * @return the notification metadata 192 * @throws JMException in case of errors 193 */ 194 protected ModelMBeanNotificationInfo[] getNotificationInfo(Object managedBean, String beanKey) 195 throws JMException { 196 return new ModelMBeanNotificationInfo[0]; 197 } 198 199 200 /** 201 * Get the attribute metadata for the MBean resource. Subclasses should implement 202 * this method to return the appropriate metadata for all the attributes that should 203 * be exposed in the management interface for the managed resource. 204 * @param managedBean the bean instance (might be an AOP proxy) 205 * @param beanKey the key associated with the MBean in the beans map 206 * of the {@code MBeanExporter} 207 * @return the attribute metadata 208 * @throws JMException in case of errors 209 */ 210 protected abstract ModelMBeanAttributeInfo[] getAttributeInfo(Object managedBean, String beanKey) 211 throws JMException; 212 213 /** 214 * Get the operation metadata for the MBean resource. Subclasses should implement 215 * this method to return the appropriate metadata for all operations that should 216 * be exposed in the management interface for the managed resource. 217 * @param managedBean the bean instance (might be an AOP proxy) 218 * @param beanKey the key associated with the MBean in the beans map 219 * of the {@code MBeanExporter} 220 * @return the operation metadata 221 * @throws JMException in case of errors 222 */ 223 protected abstract ModelMBeanOperationInfo[] getOperationInfo(Object managedBean, String beanKey) 224 throws JMException; 225 226}