1 7 8 package com.sun.jmx.mbeanserver; 9 10 11 import java.lang.reflect.Constructor ; 13 import java.lang.reflect.Method ; 14 import java.lang.reflect.Modifier ; 15 import java.util.ArrayList ; 16 import java.util.List ; 17 import java.util.Iterator ; 18 19 import javax.management.IntrospectionException ; 21 import javax.management.MBeanAttributeInfo ; 22 import javax.management.MBeanConstructorInfo ; 23 import javax.management.MBeanInfo ; 24 import javax.management.MBeanOperationInfo ; 25 import javax.management.MBeanParameterInfo ; 26 import javax.management.NotCompliantMBeanException ; 27 28 29 35 public class Introspector { 36 37 38 43 44 private static final String attributeDescription = 45 "Attribute exposed for management"; 46 private static final String operationDescription = 47 "Operation exposed for management"; 48 private static final String constructorDescription = 49 "Public constructor of the MBean"; 50 private static final String mbeanInfoDescription = 51 "Information on the management interface of the MBean"; 52 53 54 59 60 private Introspector() { 62 63 66 } 67 68 73 74 94 public static final boolean isDynamic(final Class c) { 95 return javax.management.DynamicMBean .class.isAssignableFrom(c); 97 } 98 99 114 public static void testCreation(Class c) 115 throws NotCompliantMBeanException { 116 final int mods = c.getModifiers(); 118 if (Modifier.isAbstract(mods) || Modifier.isInterface(mods)) { 119 throw new NotCompliantMBeanException ("MBean class must be concrete"); 120 } 121 122 final Constructor [] consList = c.getConstructors(); 124 if (consList.length == 0) { 125 throw new NotCompliantMBeanException ("MBean class must have public constructor"); 126 } 127 } 128 129 139 public static MBeanInfo testCompliance(Class baseClass) 140 throws NotCompliantMBeanException { 141 142 145 if (isDynamic(baseClass)) 148 return null; 149 150 return testCompliance(baseClass, null); 151 } 152 153 154 164 static MBeanInfo testCompliance(final Class baseClass, 165 Class mbeanInterface) 166 throws NotCompliantMBeanException { 167 168 if (baseClass.isInterface()) 169 throw new NotCompliantMBeanException (baseClass.getName() + 170 " must be a class."); 171 if (mbeanInterface == null) 174 mbeanInterface = getStandardMBeanInterface(baseClass); 176 else if (! mbeanInterface.isAssignableFrom(baseClass)) { 177 final String msg = 179 baseClass.getName() + " does not implement the " + 180 mbeanInterface.getName() + " interface"; 181 throw new NotCompliantMBeanException (msg); 182 } else if (! mbeanInterface.isInterface()) { 183 final String msg = 185 baseClass.getName() + ": " + mbeanInterface.getName() + 186 " is not an interface"; 187 throw new NotCompliantMBeanException (msg); 188 } 189 190 191 if (mbeanInterface == null) { 192 final String baseClassName = baseClass.getName(); 195 final String msg = 196 baseClassName + " does not implement the " + baseClassName + 197 "MBean interface or the DynamicMBean interface"; 198 throw new NotCompliantMBeanException (msg); 199 } 200 201 final int mods = mbeanInterface.getModifiers(); 202 if (!Modifier.isPublic(mods)) 203 throw new NotCompliantMBeanException (mbeanInterface.getName() + 204 " implemented by " + 205 baseClass.getName() + 206 " must be public"); 207 208 return (introspect(baseClass, mbeanInterface)); 209 } 210 211 212 223 public static Class getMBeanInterface(Class baseClass) { 224 225 228 if (isDynamic(baseClass)) return null; 231 232 return getStandardMBeanInterface(baseClass); 233 } 234 235 246 static Class getStandardMBeanInterface(Class baseClass) { 247 248 251 Class current = baseClass; 252 Class mbeanInterface = null; 253 254 while (current != null) { 255 mbeanInterface = 256 findMBeanInterface(current, current.getName()); 257 if (mbeanInterface != null) break; 258 current = current.getSuperclass(); 259 } 260 return mbeanInterface; 261 } 262 263 268 269 270 274 private static Class findMBeanInterface(Class aClass, String aName) { 275 Class current = aClass; 276 while (current != null) { 277 final Class [] interfaces = current.getInterfaces(); 278 final int len = interfaces.length; 279 for (int i=0;i<len;i++) { 280 final Class inter = 281 implementsMBean(interfaces[i], aName); 282 if (inter != null) return inter; 283 } 284 current = current.getSuperclass(); 285 } 286 return null; 287 } 288 289 290 299 private static MBeanInfo introspect(Class baseClass, Class beanClass) 300 throws NotCompliantMBeanException { 301 302 305 List attributes = 306 new ArrayList (); 307 List operations = 308 new ArrayList (); 309 310 Method methodList[] = beanClass.getMethods(); 311 312 for (int i = 0; i < methodList.length; i++) { 314 Method method = methodList[i]; 315 String name = method.getName(); 316 Class argTypes[] = method.getParameterTypes(); 317 Class resultType = method.getReturnType(); 318 int argCount = argTypes.length; 319 320 try { 321 final MBeanAttributeInfo attr; 322 323 if (name.startsWith("get") && !name.equals("get") 324 && argCount == 0 && !resultType.equals(void.class)) { 325 attr = new MBeanAttributeInfo (name.substring(3), 327 attributeDescription, 328 method, null); 329 } else if (name.startsWith("set") && !name.equals("set") 330 && argCount == 1 && resultType.equals(void.class)) { 331 attr = new MBeanAttributeInfo (name.substring(3), 333 attributeDescription, 334 null, method); 335 } else if (name.startsWith("is") && !name.equals("is") 336 && argCount == 0 337 && resultType.equals(boolean.class)) { 338 attr = new MBeanAttributeInfo (name.substring(2), 340 attributeDescription, 341 method, null); 342 } else { 343 attr = null; 345 } 346 347 if (attr != null) { 348 if (testConsistency(attributes, attr)) 349 attributes.add(attr); 350 } else { 351 final MBeanOperationInfo oper = 352 new MBeanOperationInfo (operationDescription, method); 353 operations.add(oper); 354 } 355 } catch (IntrospectionException e) { 356 error("introspect", e); 358 } 359 } 360 361 return constructResult(baseClass, attributes, operations); 362 } 363 364 377 private static boolean testConsistency(List attributes, 378 MBeanAttributeInfo attr) 379 throws NotCompliantMBeanException { 380 for (Iterator it = attributes.iterator(); it.hasNext(); ) { 381 MBeanAttributeInfo mb = (MBeanAttributeInfo ) it.next(); 382 if (mb.getName().equals(attr.getName())) { 383 if ((attr.isReadable() && mb.isReadable()) && 384 (attr.isIs() != mb.isIs())) { 385 final String msg = 386 "Conflicting getters for attribute " + mb.getName(); 387 throw new NotCompliantMBeanException (msg); 388 } 389 if (!mb.getType().equals(attr.getType())) { 390 if (mb.isWritable() && attr.isWritable()) { 391 final String msg = 392 "Type mismatch between parameters of set" + 393 mb.getName() + " methods"; 394 throw new NotCompliantMBeanException (msg); 395 } else { 396 final String msg = 397 "Type mismatch between parameters of get or is" + 398 mb.getName() + ", set" + mb.getName() + " methods"; 399 throw new NotCompliantMBeanException (msg); 400 } 401 } 402 if (attr.isReadable() && mb.isReadable()) { 403 return false; 404 } 405 if (attr.isWritable() && mb.isWritable()) { 406 return false; 407 } 408 } 409 } 410 return true; 411 } 412 413 416 static MBeanConstructorInfo [] getConstructors(Class baseClass) { 417 Constructor [] consList = baseClass.getConstructors(); 418 List constructors = new ArrayList (); 419 420 for (int i = 0; i < consList.length; i++) { 422 Constructor constructor = consList[i]; 423 MBeanConstructorInfo mc = null; 424 try { 425 mc = new MBeanConstructorInfo (constructorDescription, constructor); 426 } catch (Exception ex) { 427 mc = null; 428 } 429 if (mc != null) { 430 constructors.add(mc); 431 } 432 } 433 MBeanConstructorInfo [] resultConstructors = 435 new MBeanConstructorInfo [constructors.size()]; 436 constructors.toArray(resultConstructors); 437 return resultConstructors; 438 } 439 440 443 private static MBeanInfo constructResult(Class baseClass, 444 List attributes, 445 List operations) { 446 447 final int len = attributes.size(); 448 final MBeanAttributeInfo [] attrlist = new MBeanAttributeInfo [len]; 449 attributes.toArray(attrlist); 450 final ArrayList mergedAttributes = new ArrayList (); 451 452 for (int i=0;i<len;i++) { 453 final MBeanAttributeInfo bi = attrlist[i]; 454 455 if (bi == null) continue; 460 461 MBeanAttributeInfo att = bi; 465 466 for (int j=i+1;j<len;j++) { 473 MBeanAttributeInfo mi = attrlist[j]; 474 475 if (mi == null) continue; 480 if ((mi.getName().compareTo(bi.getName()) == 0)) { 481 attrlist[j]=null; 492 att = new MBeanAttributeInfo (bi.getName(), 493 bi.getType(), 494 attributeDescription, 495 true, true, bi.isIs()); 496 } 501 } 502 503 mergedAttributes.add(att); 508 } 509 510 final MBeanAttributeInfo [] resultAttributes = 511 new MBeanAttributeInfo [mergedAttributes.size()]; 512 mergedAttributes.toArray(resultAttributes); 513 514 final MBeanOperationInfo [] resultOperations = 515 new MBeanOperationInfo [operations.size()]; 516 operations.toArray(resultOperations); 517 518 final MBeanConstructorInfo [] resultConstructors = 519 getConstructors(baseClass); 520 521 final MBeanInfo resultMBeanInfo = 522 new MBeanInfo (baseClass.getName(), mbeanInfoDescription, 523 resultAttributes, resultConstructors, 524 resultOperations, null); 525 return resultMBeanInfo; 526 } 527 528 534 static Class implementsMBean(Class c, String clName) { 535 if (c.getName().compareTo(clName + "MBean") == 0) { 536 return c; 537 } 538 Class current = c; 539 Class [] interfaces = c.getInterfaces(); 540 for (int i = 0;i < interfaces.length; i++) { 541 542 try { 543 if (interfaces[i].getName().compareTo(clName + "MBean") == 0) { 544 return interfaces[i]; 545 } 546 } catch (Exception e) { 547 return null; 548 } 549 } 550 551 return null; 552 } 553 554 private static void error(String method,Throwable t) { 555 com.sun.jmx.trace.Trace.send(com.sun.jmx.trace.Trace.LEVEL_ERROR, 556 com.sun.jmx.trace.Trace.INFO_MBEANSERVER, 557 "Introspector", 558 method, 559 t); 560 561 } 562 } 563 | Popular Tags |