1 22 package org.jboss.mx.mxbean; 23 24 import java.lang.reflect.Method ; 25 import java.lang.reflect.Type ; 26 import java.util.HashMap ; 27 import java.util.Map ; 28 29 import javax.management.Attribute ; 30 import javax.management.AttributeList ; 31 import javax.management.AttributeNotFoundException ; 32 import javax.management.DynamicMBean ; 33 import javax.management.InvalidAttributeValueException ; 34 import javax.management.JMException ; 35 import javax.management.MBeanAttributeInfo ; 36 import javax.management.MBeanException ; 37 import javax.management.MBeanInfo ; 38 import javax.management.MBeanRegistration ; 39 import javax.management.MBeanServer ; 40 import javax.management.NotCompliantMBeanException ; 41 import javax.management.NotificationBroadcasterSupport ; 42 import javax.management.NotificationEmitter ; 43 import javax.management.ObjectName ; 44 import javax.management.ReflectionException ; 45 import javax.management.openmbean.OpenMBeanAttributeInfo ; 46 import javax.management.openmbean.OpenMBeanInfo ; 47 48 import org.jboss.logging.Logger; 49 import org.jboss.mx.server.ExceptionHandler; 50 51 58 public class MXBeanDelegate extends NotificationBroadcasterSupport implements DynamicMBean , MBeanRegistration , NotificationEmitter 59 { 60 61 private static final Logger log = Logger.getLogger(MXBeanDelegate.class); 62 63 64 private Object implementation; 65 66 67 private Class mbeanInterface; 68 69 70 private OpenMBeanInfo cachedMBeanInfo; 71 72 73 private Map <String , OpenMBeanAttributeInfo > attributeMapping; 74 75 76 private Map <String , Method > getters; 77 78 79 private Map <String , Method > setters; 80 81 82 private Map <String , Method > operations; 83 84 95 public MXBeanDelegate(Object implementation, Class mbeanInterface) throws NotCompliantMBeanException 96 { 97 this.implementation = implementation; 98 this.mbeanInterface = mbeanInterface; 99 } 100 101 112 protected MXBeanDelegate(Class mbeanInterface) throws NotCompliantMBeanException 113 { 114 this.implementation = this; 115 this.mbeanInterface = mbeanInterface; 116 } 117 118 123 public Object getImplementation() 124 { 125 return implementation; 126 } 127 128 138 public void setImplementation(Object implementation) throws NotCompliantMBeanException 139 { 140 if (implementation == null) 141 throw new IllegalArgumentException ("Null implementation"); 142 this.implementation = implementation; 143 } 144 145 150 public Class getImplementationClass() 151 { 152 return implementation.getClass(); 153 } 154 155 160 public final Class getMBeanInterface() 161 { 162 return mbeanInterface; 163 } 164 165 public Object getAttribute(String attribute) throws AttributeNotFoundException , MBeanException , ReflectionException 166 { 167 try 168 { 169 OpenMBeanAttributeInfo attributeInfo = attributeMapping.get(attribute); 170 if (attributeInfo == null) 171 throw new AttributeNotFoundException (attribute); 172 MBeanAttributeInfo mbeanAttributeInfo = (MBeanAttributeInfo ) attributeInfo; 173 if (mbeanAttributeInfo.isReadable() == false) 174 throw new AttributeNotFoundException ("Attribute is not readable: " + attribute); 175 176 Method method = getters.get(attribute); 177 if (method == null) 178 throw new NoSuchMethodException ("No method to get attribute: " + attribute); 179 180 Object result = method.invoke(implementation, new Object [0]); 181 182 return MXBeanUtils.construct(attributeInfo.getOpenType(), result, "Get attribute: " + attribute); 183 } 184 catch (Exception e) 185 { 186 JMException result = ExceptionHandler.handleException(e); 187 if (result instanceof AttributeNotFoundException ) 188 throw (AttributeNotFoundException )result; 189 if (result instanceof MBeanException ) 190 throw (MBeanException )result; 191 if (result instanceof ReflectionException ) 192 throw (ReflectionException )result; 193 throw new MBeanException (e, "Cannot get attribute: " + attribute); 194 } 195 } 196 197 public void setAttribute(Attribute attribute) throws AttributeNotFoundException , InvalidAttributeValueException , MBeanException , ReflectionException 198 { 199 try 200 { 201 String attributeName = attribute.getName(); 202 OpenMBeanAttributeInfo attributeInfo = attributeMapping.get(attributeName); 203 if (attributeInfo == null) 204 throw new AttributeNotFoundException (attributeName); 205 MBeanAttributeInfo mbeanAttributeInfo = (MBeanAttributeInfo ) attributeInfo; 206 if (mbeanAttributeInfo.isWritable() == false) 207 throw new AttributeNotFoundException ("Attribute is not writable: " + attributeName); 208 209 Method method = setters.get(attributeName); 210 if (method == null) 211 throw new NoSuchMethodException ("No method to set attribute: " + attribute); 212 213 Object value = MXBeanUtils.reconstruct(method.getGenericParameterTypes()[0], attribute.getValue(), method); 214 215 method.invoke(implementation, new Object [] { value }); 216 } 217 catch (Exception e) 218 { 219 JMException result = ExceptionHandler.handleException(e); 220 if (result instanceof AttributeNotFoundException ) 221 throw (AttributeNotFoundException )result; 222 if (result instanceof InvalidAttributeValueException ) 223 throw (InvalidAttributeValueException )result; 224 if (result instanceof MBeanException ) 225 throw (MBeanException )result; 226 if (result instanceof ReflectionException ) 227 throw (ReflectionException )result; 228 throw new MBeanException (e, "Cannot set attribute: " + attribute); 229 } 230 } 231 232 public AttributeList getAttributes(String [] attributes) 233 { 234 try 235 { 236 AttributeList attrList = new AttributeList (attributes.length); 237 for (int i = 0; i < attributes.length; i++) 238 { 239 String name = attributes[i]; 240 Object value = getAttribute(name); 241 attrList.add(new Attribute (name, value)); 242 } 243 return attrList; 244 } 245 catch (Exception e) 246 { 247 JMException result = ExceptionHandler.handleException(e); 248 throw new RuntimeException ("Cannot get attributes", result); 250 } 251 } 252 253 public AttributeList setAttributes(AttributeList attributes) 254 { 255 AttributeList result = new AttributeList (attributes.size()); 256 for (int i = 0; i < attributes.size(); ++i) 257 { 258 Attribute attr = (Attribute ) attributes.get(i); 259 String name = attr.getName(); 260 try 261 { 262 setAttribute(attr); 263 result.add(new Attribute (name, attr.getValue())); 264 } 265 catch (Throwable t) 266 { 267 JMException e = ExceptionHandler.handleException(t); 268 result.add(new Attribute (name, e)); 269 } 270 } 271 return result; 272 } 273 274 public Object invoke(String actionName, Object [] params, String [] signature) throws MBeanException , ReflectionException 275 { 276 try 277 { 278 String signatureString = getSignatureString(actionName, signature); 279 Method method = operations.get(signatureString); 280 if (method == null) 281 throw new NoSuchMethodException ("Cannot find method for operation: " + signatureString); 282 283 Object [] parameters = params; 284 if (params.length > 0) 285 { 286 parameters = new Object [params.length]; 287 Type [] parameterTypes = method.getGenericParameterTypes(); 288 for (int i = 0; i < parameters.length; ++i) 289 parameters[i] = MXBeanUtils.reconstruct(parameterTypes[i], params[i], method); 290 } 291 292 Object result = method.invoke(implementation, parameters); 293 294 if (result == null) 295 return null; 296 Type returnType = method.getGenericReturnType(); 297 return MXBeanUtils.construct(returnType, result, method); 298 } 299 catch (Exception e) 300 { 301 JMException result = ExceptionHandler.handleException(e); 302 if (result instanceof MBeanException ) 303 throw (MBeanException )result; 304 if (result instanceof ReflectionException ) 305 throw (ReflectionException )result; 306 throw new MBeanException (e, "Cannot invoke: " + actionName); 307 } 308 } 309 310 public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception 311 { 312 return name; 313 } 314 315 public void postRegister(Boolean registrationDone) 316 { 317 } 318 319 public void preDeregister() throws Exception 320 { 321 } 322 323 public void postDeregister() 324 { 325 } 326 327 public MBeanInfo getMBeanInfo() 328 { 329 OpenMBeanInfo info = getCachedMBeanInfo(); 330 if (info == null) 331 { 332 try 333 { 334 info = buildMBeanInfo(); 335 cacheMBeanInfo(info); 336 } 337 catch (NotCompliantMBeanException e) 338 { 339 log.error("Unexcepted exception", e); 340 throw new IllegalStateException ("Unexcepted exception " + e.toString()); 341 } 342 343 } 344 return (MBeanInfo ) info; 345 } 346 347 352 public OpenMBeanInfo getCachedMBeanInfo() 353 { 354 return cachedMBeanInfo; 355 } 356 357 362 public void cacheMBeanInfo(OpenMBeanInfo info) 363 { 364 cachedMBeanInfo = info; 365 Map <String , OpenMBeanAttributeInfo > attributeMapping = new HashMap <String , OpenMBeanAttributeInfo >(); 366 MBeanAttributeInfo [] attributes = info.getAttributes(); 367 for (int i = 0; i < attributes.length; ++i) 368 { 369 OpenMBeanAttributeInfo attribute = (OpenMBeanAttributeInfo ) attributes[i]; 370 attributeMapping.put(attribute.getName(), attribute); 371 } 372 this.attributeMapping = attributeMapping; 373 374 try 375 { 376 HashMap <String , Method > getters = new HashMap <String , Method >(); 377 HashMap <String , Method > setters = new HashMap <String , Method >(); 378 379 HashMap <String , Method > operations = new HashMap <String , Method >(); 380 381 Method [] methods = implementation.getClass().getMethods(); 382 for (Method method : methods) 383 { 384 String methodName = method.getName(); 385 Type [] signature = method.getGenericParameterTypes(); 386 Type returnType = method.getGenericReturnType(); 387 388 if (methodName.startsWith("set") && 389 methodName.length() > 3 && 390 signature.length == 1 && 391 returnType == Void.TYPE) 392 { 393 String key = methodName.substring(3, methodName.length()); 394 Method setter = setters.get(key); 395 if (setter != null && setter.getGenericParameterTypes()[0].equals(signature[0]) == false) 396 throw new RuntimeException ("overloaded type for attribute set: " + key); 397 setters.put(key, method); 398 } 399 else if (methodName.startsWith("get") && 400 methodName.length() > 3 && 401 signature.length == 0 && 402 returnType != Void.TYPE) 403 { 404 String key = methodName.substring(3, methodName.length()); 405 Method getter = getters.get(key); 406 if (getter != null && getter.getName().startsWith("is")) 407 throw new RuntimeException ("mixed use of get/is for attribute " + key); 408 getters.put(key, method); 409 } 410 else if (methodName.startsWith("is") && 411 methodName.length() > 2 && 412 signature.length == 0 && 413 returnType == Boolean.TYPE) 414 { 415 String key = methodName.substring(2, methodName.length()); 416 Method getter = getters.get(key); 417 if (getter != null && getter.getName().startsWith("get")) 418 throw new RuntimeException ("mixed use of get/is for attribute " + key); 419 getters.put(key, method); 420 } 421 else 422 { 423 operations.put(getSignatureString(method), method); 424 } 425 } 426 this.getters = getters; 427 this.setters = setters; 428 this.operations = operations; 429 } 430 catch (RuntimeException e) 431 { 432 log.error("Error: ", e); 433 throw e; 434 } 435 catch (Error e) 436 { 437 log.error("Error: ", e); 438 throw e; 439 } 440 } 441 442 451 public OpenMBeanInfo buildMBeanInfo() throws NotCompliantMBeanException 452 { 453 if (implementation == null) 454 throw new IllegalArgumentException ("Null implementation"); 455 456 MXBeanMetaData metadata = new MXBeanMetaData(implementation, mbeanInterface); 457 return (OpenMBeanInfo ) metadata.build(); 458 } 459 460 466 private String getSignatureString(Method method) 467 { 468 String name = method.getName(); 469 Class [] signature = method.getParameterTypes(); 470 StringBuilder buffer = new StringBuilder (512); 471 buffer.append(name); 472 buffer.append("("); 473 if (signature != null) 474 { 475 for (int i = 0; i < signature.length; i++) 476 { 477 buffer.append(signature[i].getName()); 478 if (i < signature.length-1) 479 buffer.append(","); 480 } 481 } 482 buffer.append(")"); 483 return buffer.toString(); 484 } 485 486 493 private String getSignatureString(String operation, String [] signature) 494 { 495 StringBuilder buffer = new StringBuilder (512); 496 buffer.append(operation); 497 buffer.append("("); 498 if (signature != null) 499 { 500 for (int i = 0; i < signature.length; i++) 501 { 502 buffer.append(signature[i]); 503 if (i < signature.length-1) 504 buffer.append(","); 505 } 506 } 507 buffer.append(")"); 508 return buffer.toString(); 509 } 510 } 511 | Popular Tags |