1 22 package org.jboss.mx.mxbean; 23 24 import java.lang.reflect.Constructor ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.Type ; 27 import java.util.ArrayList ; 28 import java.util.Collection ; 29 import java.util.HashMap ; 30 import java.util.List ; 31 32 import javax.management.IntrospectionException ; 33 import javax.management.MBeanInfo ; 34 import javax.management.MBeanNotificationInfo ; 35 import javax.management.MBeanOperationInfo ; 36 import javax.management.NotCompliantMBeanException ; 37 import javax.management.NotificationBroadcaster ; 38 import javax.management.openmbean.OpenMBeanAttributeInfo ; 39 import javax.management.openmbean.OpenMBeanAttributeInfoSupport ; 40 import javax.management.openmbean.OpenMBeanConstructorInfo ; 41 import javax.management.openmbean.OpenMBeanConstructorInfoSupport ; 42 import javax.management.openmbean.OpenMBeanInfoSupport ; 43 import javax.management.openmbean.OpenMBeanOperationInfo ; 44 import javax.management.openmbean.OpenMBeanOperationInfoSupport ; 45 import javax.management.openmbean.OpenMBeanParameterInfo ; 46 import javax.management.openmbean.OpenMBeanParameterInfoSupport ; 47 import javax.management.openmbean.OpenType ; 48 49 import org.jboss.mx.metadata.AbstractBuilder; 50 51 59 public class MXBeanMetaData extends AbstractBuilder 60 { 61 62 private Object mbeanInstance; 63 64 65 private Class <?> mbeanClass; 66 67 68 private Class <?> mbeanInterface; 69 70 76 public static Class <?> findMXBeanInterface(Class <?> mbeanClass) 77 { 78 Class <?> concrete = mbeanClass; 79 while (null != concrete) 80 { 81 Class result = findMXBeanInterface(concrete, concrete.getInterfaces()); 82 if (null != result) 83 return result; 84 concrete = concrete.getSuperclass(); 85 } 86 return null; 87 } 88 89 96 private static Class <?> findMXBeanInterface(Class <?> concrete, Class <?>[] interfaces) 97 { 98 String mxName = concrete.getName() + "MXBean"; 99 String stdName = concrete.getName() + "MBean"; 100 101 for (Class <?> intf : interfaces) 102 { 103 String name = intf.getName(); 104 if (mxName.equals(name) || stdName.equals(name)) 105 return intf; 106 107 MXBean mxBean = intf.getAnnotation(MXBean.class); 108 if (mxBean != null && mxBean.value()) 109 return intf; 110 } 111 return null; 112 } 113 114 120 public MXBeanMetaData(Object mbeanInstance) throws NotCompliantMBeanException 121 { 122 this(mbeanInstance.getClass()); 123 this.mbeanInstance = mbeanInstance; 124 } 125 126 132 public MXBeanMetaData(Class <?> mbeanClass) throws NotCompliantMBeanException 133 { 134 this.mbeanClass = mbeanClass; 135 this.mbeanInterface = findMXBeanInterface(mbeanClass); 136 if (this.mbeanInterface == null) 137 throw new NotCompliantMBeanException ("Cannot obtain MXBean interface for: " + mbeanClass); 138 } 139 140 147 public MXBeanMetaData(Object mbeanInstance, Class <?> mbeanInterface) throws NotCompliantMBeanException 148 { 149 this.mbeanInstance = mbeanInstance; 150 this.mbeanClass = mbeanInstance.getClass(); 151 this.mbeanInterface = mbeanInterface; 152 if (this.mbeanInterface == null) 153 this.mbeanInterface = MXBeanMetaData.findMXBeanInterface(mbeanClass); 154 if (this.mbeanInterface == null) 155 throw new NotCompliantMBeanException ("Cannot obtain mxbean interface for: " + mbeanClass); 156 if (this.mbeanInterface.isInterface() == false) 157 throw new NotCompliantMBeanException ("Management interface is not an interface: " + mbeanInterface); 158 } 159 160 165 public Class <?> getMBeanInterface() 166 { 167 return mbeanInterface; 168 } 169 170 public MBeanInfo build() throws NotCompliantMBeanException 171 { 172 try 173 { 174 if (mbeanInterface == null) 176 throw new NotCompliantMBeanException ("The mbean does not implement a management interface"); 177 if (mbeanInstance != null && mbeanInterface.isInstance(mbeanInstance) == false) 178 throw new NotCompliantMBeanException ("The mbean does not implement its management interface " + mbeanInterface.getName()); 179 180 OpenMBeanConstructorInfo [] constructorInfo = buildConstructors(); 181 182 HashMap <String , Method > getters = new HashMap <String , Method >(); 183 HashMap <String , Method > setters = new HashMap <String , Method >(); 184 185 HashMap <String , OpenMBeanOperationInfo > operInfo = new HashMap <String , OpenMBeanOperationInfo >(); 186 List <OpenMBeanAttributeInfo > attrInfo = new ArrayList <OpenMBeanAttributeInfo >(); 187 188 Method [] methods = mbeanInterface.getMethods(); 189 for (Method method : methods) 190 { 191 String methodName = method.getName(); 192 Type [] signature = method.getGenericParameterTypes(); 193 Type returnType = method.getGenericReturnType(); 194 195 if (methodName.startsWith("set") && 196 methodName.length() > 3 && 197 signature.length == 1 && 198 returnType == Void.TYPE) 199 { 200 String key = methodName.substring(3, methodName.length()); 201 Method setter = setters.get(key); 202 if (setter != null && setter.getGenericParameterTypes()[0].equals(signature[0]) == false) 203 throw new IntrospectionException ("overloaded type for attribute set: " + key); 204 setters.put(key, method); 205 } 206 else if (methodName.startsWith("get") && 207 methodName.length() > 3 && 208 signature.length == 0 && 209 returnType != Void.TYPE) 210 { 211 String key = methodName.substring(3, methodName.length()); 212 Method getter = getters.get(key); 213 if (getter != null && getter.getName().startsWith("is")) 214 throw new IntrospectionException ("mixed use of get/is for attribute " + key); 215 getters.put(key, method); 216 } 217 else if (methodName.startsWith("is") && 218 methodName.length() > 2 && 219 signature.length == 0 && 220 isBooleanReturn(returnType)) 221 { 222 String key = methodName.substring(2, methodName.length()); 223 Method getter = getters.get(key); 224 if (getter != null && getter.getName().startsWith("get")) 225 throw new IntrospectionException ("mixed use of get/is for attribute " + key); 226 getters.put(key, method); 227 } 228 else 229 { 230 OpenMBeanOperationInfo info = buildOperation(method); 231 operInfo.put(getSignatureString(method), info); 232 } 233 } 234 235 String [] keys = getters.keySet().toArray(new String [getters.size()]); 236 for (String key : keys) 237 { 238 Method getter = getters.remove(key); 239 Method setter = setters.remove(key); 240 OpenMBeanAttributeInfo info = buildAttribute(key, getter, setter); 241 attrInfo.add(info); 242 } 243 244 for (String key : setters.keySet()) 245 { 246 Method setter = setters.remove(key); 247 OpenMBeanAttributeInfo info = buildAttribute(key, null, setter); 248 attrInfo.add(info); 249 } 250 251 OpenMBeanAttributeInfo [] attributeInfo = attrInfo.toArray(new OpenMBeanAttributeInfo [attrInfo.size()]); 252 Collection <OpenMBeanOperationInfo > operations = operInfo.values(); 253 OpenMBeanOperationInfo [] operationInfo = operations.toArray(new OpenMBeanOperationInfo [operations.size()]); 254 255 MBeanNotificationInfo [] notifications = null; 256 if (mbeanInstance instanceof NotificationBroadcaster ) 257 notifications = ((NotificationBroadcaster ) mbeanInstance).getNotificationInfo(); 258 else 259 notifications = new MBeanNotificationInfo [0]; 260 261 return buildMBeanInfo(attributeInfo, constructorInfo, operationInfo, notifications); 262 263 } 264 catch (Throwable t) 265 { 266 NotCompliantMBeanException e = new NotCompliantMBeanException ("Error generating OpenMBeanInfo."); 267 e.initCause(t); 268 throw e; 269 } 270 } 271 272 278 private OpenMBeanConstructorInfo [] buildConstructors() throws Exception 279 { 280 Constructor <?>[] constructors = mbeanClass.getConstructors(); 281 OpenMBeanConstructorInfo [] constructorInfo = new OpenMBeanConstructorInfo [constructors.length]; 282 for (int i = 0; i < constructors.length; ++i) 283 constructorInfo[i] = buildConstructor(constructors[i]); 284 return constructorInfo; 285 } 286 287 294 private OpenMBeanConstructorInfo buildConstructor(Constructor <?> constructor) throws Exception 295 { 296 Type [] parameterTypes = constructor.getGenericParameterTypes(); 297 OpenMBeanParameterInfo [] parameterInfo = new OpenMBeanParameterInfo [parameterTypes.length]; 298 for (int i = 0; i < parameterTypes.length; ++i) 299 parameterInfo[i] = buildParameter(i, parameterTypes[i]); 300 return new OpenMBeanConstructorInfoSupport ("MBean Constructor.", "MBean Constructor.", parameterInfo); 301 } 302 303 311 private OpenMBeanParameterInfo buildParameter(int i, Type parameterType) throws Exception 312 { 313 OpenType openType = MXBeanUtils.getOpenType(parameterType); 314 return new OpenMBeanParameterInfoSupport ("arg" + i, "MBean Parameter.", openType); 315 } 316 317 326 private OpenMBeanAttributeInfo buildAttribute(String attrName, Method getter, Method setter) throws Exception 327 { 328 boolean isReadable = (getter != null); 329 boolean isWritable = (setter != null); 330 boolean isIs = false; 331 332 OpenType openType = null; 333 if (getter != null) 334 { 335 openType = MXBeanUtils.getOpenType(getter.getGenericReturnType()); 336 if (getter.getName().startsWith("is")) 337 isIs = true; 338 } 339 else 340 { 341 openType = MXBeanUtils.getOpenType(setter.getGenericParameterTypes()[0]); 342 } 343 344 return new OpenMBeanAttributeInfoSupport (attrName, attrName, openType, isReadable, isWritable, isIs); 345 } 346 347 354 private OpenMBeanOperationInfo buildOperation(Method method) throws Exception 355 { 356 Type [] parameterTypes = method.getGenericParameterTypes(); 357 OpenMBeanParameterInfo [] parameterInfo = new OpenMBeanParameterInfo [parameterTypes.length]; 358 for (int i = 0; i < parameterTypes.length; ++i) 359 parameterInfo[i] = buildParameter(i, parameterTypes[i]); 360 OpenType openType = MXBeanUtils.getOpenType(method.getGenericReturnType()); 361 return new OpenMBeanOperationInfoSupport (method.getName(), method.getName(), parameterInfo, openType, MBeanOperationInfo.ACTION); 362 } 363 364 374 private OpenMBeanInfoSupport buildMBeanInfo(OpenMBeanAttributeInfo [] attributes, OpenMBeanConstructorInfo [] constructors, OpenMBeanOperationInfo [] operations, MBeanNotificationInfo [] notifications) throws Exception 375 { 376 return new OpenMBeanInfoSupport (mbeanClass.getName(), mbeanClass.getName(), attributes, constructors, operations, notifications); 377 } 378 379 386 private boolean isBooleanReturn(Type returnType) 387 { 388 return returnType == Boolean.TYPE; 389 } 390 391 397 private String getSignatureString(Method method) 398 { 399 String name = method.getName(); 400 Class [] signature = method.getParameterTypes(); 401 StringBuffer buffer = new StringBuffer (512); 402 buffer.append(name); 403 buffer.append("("); 404 if (signature != null) 405 { 406 for (int i = 0; i < signature.length; i++) 407 { 408 buffer.append(signature[i].getName()); 409 if (i < signature.length-1) 410 buffer.append(","); 411 } 412 } 413 buffer.append(")"); 414 return buffer.toString(); 415 } 416 } 417 418 | Popular Tags |