1 7 8 package com.sun.jmx.mbeanserver; 9 10 11 import static com.sun.jmx.mbeanserver.Util.*; 12 13 import java.lang.ref.WeakReference ; 14 import java.lang.reflect.Array ; 15 import java.lang.reflect.Constructor ; 16 import java.lang.reflect.InvocationTargetException ; 17 import java.lang.reflect.Method ; 18 import java.lang.reflect.Type ; 19 import java.util.List ; 20 import java.util.WeakHashMap ; 21 22 import javax.management.Descriptor ; 23 import javax.management.ImmutableDescriptor ; 24 import javax.management.InvalidAttributeValueException ; 25 import javax.management.MBeanAttributeInfo ; 26 import javax.management.MBeanConstructorInfo ; 27 import javax.management.MBeanException ; 28 import javax.management.MBeanInfo ; 29 import javax.management.MBeanNotificationInfo ; 30 import javax.management.MBeanOperationInfo ; 31 import javax.management.NotCompliantMBeanException ; 32 import javax.management.NotificationBroadcaster ; 33 import javax.management.ReflectionException ; 34 35 45 53 abstract class MBeanIntrospector<M> { 54 static final class PerInterfaceMap<M> 55 extends WeakHashMap <Class <?>, WeakReference <PerInterface<M>>> {} 56 57 58 abstract PerInterfaceMap<M> getPerInterfaceMap(); 59 63 abstract MBeanInfoMap getMBeanInfoMap(); 64 65 66 abstract MBeanAnalyzer<M> getAnalyzer(Class <?> mbeanInterface) 67 throws NotCompliantMBeanException ; 68 69 70 abstract boolean isMXBean(); 71 72 73 abstract M mFrom(Method m); 74 75 76 abstract String getName(M m); 77 78 83 abstract Type getGenericReturnType(M m); 84 85 89 abstract Type [] getGenericParameterTypes(M m); 90 91 96 abstract String [] getSignature(M m); 97 98 103 abstract void checkMethod(M m) throws IllegalArgumentException ; 104 105 111 116 abstract Object invokeM2(M m, Object target, Object [] args, Object cookie) 117 throws InvocationTargetException , IllegalAccessException , 118 MBeanException ; 119 120 124 abstract boolean validParameter(M m, Object value, int paramNo, 125 Object cookie); 126 127 132 abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, 133 M getter, M setter); 134 138 abstract MBeanOperationInfo getMBeanOperationInfo(String operationName, 139 M operation); 140 141 145 abstract Descriptor getBasicMBeanDescriptor(); 146 147 152 abstract Descriptor getMBeanDescriptor(Class <?> resourceClass); 153 154 155 final PerInterface<M> getPerInterface(Class <?> mbeanInterface) 156 throws NotCompliantMBeanException { 157 PerInterfaceMap<M> map = getPerInterfaceMap(); 158 synchronized (map) { 159 WeakReference <PerInterface<M>> wr = map.get(mbeanInterface); 160 PerInterface<M> pi = (wr == null) ? null : wr.get(); 161 if (pi == null) { 162 try { 163 MBeanAnalyzer<M> analyzer = getAnalyzer(mbeanInterface); 164 MBeanInfo mbeanInfo = 165 makeInterfaceMBeanInfo(mbeanInterface, analyzer); 166 pi = new PerInterface<M>(mbeanInterface, this, analyzer, 167 mbeanInfo); 168 wr = new WeakReference <PerInterface<M>>(pi); 169 map.put(mbeanInterface, wr); 170 } catch (Exception x) { 171 throw Introspector.throwException(mbeanInterface,x); 172 } 173 } 174 return pi; 175 } 176 } 177 178 186 private MBeanInfo makeInterfaceMBeanInfo(Class <?> mbeanInterface, 187 MBeanAnalyzer<M> analyzer) { 188 final MBeanInfoMaker maker = new MBeanInfoMaker(); 189 analyzer.visit(maker); 190 final String description = 191 "Information on the management interface of the MBean"; 192 return maker.makeMBeanInfo(mbeanInterface, description); 193 } 194 195 196 final boolean consistent(M getter, M setter) { 197 return (getter == null || setter == null || 198 getGenericReturnType(getter).equals(getGenericParameterTypes(setter)[0])); 199 } 200 201 205 final Object invokeM(M m, Object target, Object [] args, Object cookie) 206 throws MBeanException , ReflectionException { 207 try { 208 return invokeM2(m, target, args, cookie); 209 } catch (InvocationTargetException e) { 210 unwrapInvocationTargetException(e); 211 throw new RuntimeException (e); } catch (IllegalAccessException e) { 213 throw new ReflectionException (e, e.toString()); 214 } 215 219 } 220 221 225 233 final void invokeSetter(String name, M setter, Object target, Object arg, 234 Object cookie) 235 throws MBeanException , ReflectionException , 236 InvalidAttributeValueException { 237 try { 238 invokeM2(setter, target, new Object [] {arg}, cookie); 239 } catch (IllegalAccessException e) { 240 throw new ReflectionException (e, e.toString()); 241 } catch (RuntimeException e) { 242 maybeInvalidParameter(name, setter, arg, cookie); 243 throw e; 244 } catch (InvocationTargetException e) { 245 maybeInvalidParameter(name, setter, arg, cookie); 246 unwrapInvocationTargetException(e); 247 } 248 } 249 250 private void maybeInvalidParameter(String name, M setter, Object arg, 251 Object cookie) 252 throws InvalidAttributeValueException { 253 if (!validParameter(setter, arg, 0, cookie)) { 254 final String msg = 255 "Invalid value for attribute " + name + ": " + arg; 256 throw new InvalidAttributeValueException (msg); 257 } 258 } 259 260 static boolean isValidParameter(Method m, Object value, int paramNo) { 261 Class <?> c = m.getParameterTypes()[paramNo]; 262 try { 263 Object a = Array.newInstance(c, 1); 267 Array.set(a, 0, value); 268 return true; 269 } catch (IllegalArgumentException e) { 270 return false; 271 } 272 } 273 274 private static void 275 unwrapInvocationTargetException(InvocationTargetException e) 276 throws MBeanException { 277 Throwable t = e.getCause(); 278 if (t instanceof RuntimeException ) 279 throw (RuntimeException ) t; 280 else if (t instanceof Error ) 281 throw (Error ) t; 282 else 283 throw new MBeanException ((Exception ) t, 284 (t == null ? null : t.toString())); 285 } 286 287 288 private class MBeanInfoMaker implements MBeanAnalyzer.MBeanVisitor<M> { 289 290 public void visitAttribute(String attributeName, 291 M getter, 292 M setter) { 293 MBeanAttributeInfo mbai = 294 getMBeanAttributeInfo(attributeName, getter, setter); 295 296 attrs.add(mbai); 297 } 298 299 public void visitOperation(String operationName, 300 M operation) { 301 MBeanOperationInfo mboi = 302 getMBeanOperationInfo(operationName, operation); 303 304 ops.add(mboi); 305 } 306 307 309 MBeanInfo makeMBeanInfo(Class <?> mbeanInterface, 310 String description) { 311 final MBeanAttributeInfo [] attrArray = 312 attrs.toArray(new MBeanAttributeInfo [0]); 313 final MBeanOperationInfo [] opArray = 314 ops.toArray(new MBeanOperationInfo [0]); 315 final String interfaceClassName = 316 "interfaceClassName=" + mbeanInterface.getName(); 317 final Descriptor interfDescriptor = 318 new ImmutableDescriptor (interfaceClassName); 319 final Descriptor mbeanDescriptor = getBasicMBeanDescriptor(); 320 final Descriptor annotatedDescriptor = 321 Introspector.descriptorForElement(mbeanInterface); 322 final Descriptor descriptor = 323 DescriptorCache.getInstance().union(interfDescriptor, 324 mbeanDescriptor, 325 annotatedDescriptor); 326 327 return new MBeanInfo (mbeanInterface.getName(), 328 description, 329 attrArray, 330 null, 331 opArray, 332 null, 333 descriptor); 334 } 335 336 private final List <MBeanAttributeInfo > attrs = newList(); 337 private final List <MBeanOperationInfo > ops = newList(); 338 } 339 340 351 static class MBeanInfoMap 352 extends WeakHashMap <Class <?>, WeakHashMap <Class <?>, MBeanInfo >> { 353 } 354 355 359 final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) { 360 MBeanInfo mbi = 361 getClassMBeanInfo(resource.getClass(), perInterface); 362 MBeanNotificationInfo [] notifs = findNotifications(resource); 363 if (notifs == null || notifs.length == 0) 364 return mbi; 365 else { 366 return new MBeanInfo (mbi.getClassName(), 367 mbi.getDescription(), 368 mbi.getAttributes(), 369 mbi.getConstructors(), 370 mbi.getOperations(), 371 notifs, 372 mbi.getDescriptor()); 373 } 374 } 375 376 383 final MBeanInfo getClassMBeanInfo(Class <?> resourceClass, 384 PerInterface<M> perInterface) { 385 MBeanInfoMap map = getMBeanInfoMap(); 386 synchronized (map) { 387 WeakHashMap <Class <?>, MBeanInfo > intfMap = map.get(resourceClass); 388 if (intfMap == null) { 389 intfMap = new WeakHashMap <Class <?>, MBeanInfo >(); 390 map.put(resourceClass, intfMap); 391 } 392 Class <?> intfClass = perInterface.getMBeanInterface(); 393 MBeanInfo mbi = intfMap.get(intfClass); 394 if (mbi == null) { 395 MBeanInfo imbi = perInterface.getMBeanInfo(); 396 Descriptor descriptor = 397 ImmutableDescriptor.union(imbi.getDescriptor(), 398 getMBeanDescriptor(resourceClass)); 399 mbi = new MBeanInfo (resourceClass.getName(), 400 imbi.getDescription(), 401 imbi.getAttributes(), 402 findConstructors(resourceClass), 403 imbi.getOperations(), 404 (MBeanNotificationInfo []) null, 405 descriptor); 406 intfMap.put(intfClass, mbi); 407 } 408 return mbi; 409 } 410 } 411 412 static MBeanNotificationInfo [] findNotifications(Object moi) { 413 if (!(moi instanceof NotificationBroadcaster )) 414 return null; 415 MBeanNotificationInfo [] mbn = 416 ((NotificationBroadcaster ) moi).getNotificationInfo(); 417 if (mbn == null) 418 return null; 419 MBeanNotificationInfo [] result = 420 new MBeanNotificationInfo [mbn.length]; 421 for (int i = 0; i < mbn.length; i++) { 422 MBeanNotificationInfo ni = mbn[i]; 423 if (ni.getClass() != MBeanNotificationInfo .class) 424 ni = (MBeanNotificationInfo ) ni.clone(); 425 result[i] = ni; 426 } 427 return result; 428 } 429 430 private static MBeanConstructorInfo [] findConstructors(Class <?> c) { 431 Constructor [] cons = c.getConstructors(); 432 MBeanConstructorInfo [] mbc = new MBeanConstructorInfo [cons.length]; 433 for (int i = 0; i < cons.length; i++) { 434 final String descr = "Public constructor of the MBean"; 435 mbc[i] = new MBeanConstructorInfo (descr, cons[i]); 436 } 437 return mbc; 438 } 439 440 } 441 | Popular Tags |