1 package org.sapia.soto.jmx; 2 3 import org.sapia.soto.util.matcher.PathPattern; 4 import org.sapia.soto.util.matcher.Pattern; 5 6 import java.lang.reflect.InvocationTargetException ; 7 import java.lang.reflect.Method ; 8 import java.lang.reflect.Modifier ; 9 10 import java.util.ArrayList ; 11 import java.util.HashMap ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 import java.util.Map ; 15 16 import javax.management.Attribute ; 17 import javax.management.AttributeNotFoundException ; 18 import javax.management.IntrospectionException ; 19 import javax.management.MBeanAttributeInfo ; 20 import javax.management.MBeanConstructorInfo ; 21 import javax.management.MBeanException ; 22 import javax.management.MBeanInfo ; 23 import javax.management.MBeanNotificationInfo ; 24 import javax.management.MBeanOperationInfo ; 25 import javax.management.ReflectionException ; 26 27 28 52 public class MBeanDescriptor { 53 public static final String DEFAULT_DESC = "No description available"; 54 private Map _attributes = new HashMap (); 55 private Map _operations = new HashMap (); 56 private MBeanInfo _info; 57 private String _className; 58 private String _description = DEFAULT_DESC; 59 private Object _bean; 60 61 64 private MBeanDescriptor(Object bean) { 65 _bean = bean; 66 } 67 68 73 public void setDescription(String desc) { 74 _description = desc; 75 } 76 77 82 public Object getBean() { 83 return _bean; 84 } 85 86 93 public static MBeanDescriptor newInstanceFor(Object obj) 94 throws IntrospectionException { 95 MBeanDescriptor desc = new MBeanDescriptor(obj); 96 Method [] methods = obj.getClass().getDeclaredMethods(); 97 98 for (int i = 0; i < methods.length; i++) { 99 if (((methods[i].getModifiers() & Modifier.STATIC) != 0) && 100 ((methods[i].getModifiers() & Modifier.PUBLIC) == 0)) { 101 continue; 102 } 103 104 if (MethodUtils.isSetter(methods[i]) || MethodUtils.isGetter(methods[i]) || 105 MethodUtils.isBoolean(methods[i])) { 106 desc.getAttributeDescriptorFor(methods[i]); 107 } else if (MethodUtils.isOperation(methods[i])) { 108 desc.getOperationDescriptor(methods[i]); 109 } 110 } 111 112 desc.init(); 113 114 return desc; 115 } 116 117 128 public AttributeDescriptor getAttributeDescriptorFor(Method method) 129 throws IllegalArgumentException { 130 String name = null; 131 MethodInfo info; 132 133 if (MethodUtils.isSetter(method)) { 134 name = MethodUtils.getAttributeName(method, MethodUtils.SET_PREFIX); 135 info = new MethodInfo(name, method.getParameterTypes()); 136 } else if (MethodUtils.isGetter(method)) { 137 name = MethodUtils.getAttributeName(method, MethodUtils.GET_PREFIX); 138 info = new MethodInfo(name, new Class [] { method.getReturnType() }); 139 } else if (MethodUtils.isBoolean(method)) { 140 name = MethodUtils.getAttributeName(method, "is"); 141 info = new MethodInfo(name, new Class [] { method.getReturnType() }); 142 } else { 143 throw new IllegalArgumentException ("Method " + method + 144 " does not start with set/get/is prefix"); 145 } 146 147 AttributeDescriptor desc = (AttributeDescriptor) _attributes.get(info); 148 149 if (desc == null) { 150 desc = new AttributeDescriptor(); 151 desc.setAttributeName(name); 152 initAttributeDesc(desc, method); 153 _attributes.put(info, desc); 154 } else { 155 initAttributeDesc(desc, method); 156 } 157 158 return desc; 159 } 160 161 171 public OperationDescriptor getOperationDescriptor(Method method) { 172 MethodInfo toCompare = new MethodInfo(method); 173 OperationDescriptor od = (OperationDescriptor) _operations.get(toCompare); 174 175 if (od == null) { 176 if (!MethodUtils.isOperation(method)) { 177 throw new IllegalArgumentException ("Method " + method + 178 " does not correspond to a MBean operation"); 179 } 180 181 od = new OperationDescriptor(); 182 _operations.put(toCompare, od); 183 initOperationDesc(od, method); 184 } 185 186 return od; 187 } 188 189 195 public MBeanInfo getMBeanInfo() { 196 return _info; 197 } 198 199 208 public Object getAttribute(String name) 209 throws AttributeNotFoundException , MBeanException , ReflectionException { 210 List attrs; 211 212 try { 213 attrs = getAttributeDescriptorsFor(name, null); 214 } catch (IntrospectionException e) { 215 throw new MBeanException (e, "Get value for attribute: " + name); 216 } 217 218 if (attrs.size() == 0) { 219 throw new AttributeNotFoundException ("No attribute for: " + name); 220 } 221 222 AttributeDescriptor ad = (AttributeDescriptor) attrs.get(0); 223 224 if (ad == null) { 225 throw new AttributeNotFoundException (name); 226 } 227 228 if (ad.getReadMethod() == null) { 229 throw new AttributeNotFoundException ("Attribute '" + name + 230 "' is not readable"); 231 } 232 233 try { 234 return ad.getReadMethod().invoke(_bean, new Object [0]); 235 } catch (IllegalAccessException e) { 236 throw new ReflectionException (e, 237 "Attribute '" + name + "' is not accessible"); 238 } catch (InvocationTargetException e) { 239 Exception err; 240 241 if (e.getTargetException() instanceof Exception ) { 242 err = (Exception ) e.getTargetException(); 243 } else { 244 err = e; 245 } 246 247 throw new MBeanException (err, "Error occured reading attribute: " + name); 248 } 249 } 250 251 259 public void setAttribute(Attribute attr) 260 throws AttributeNotFoundException , MBeanException , ReflectionException { 261 List attrs; 262 263 try { 264 attrs = getAttributeDescriptorsFor(attr.getName(), null); 265 } catch (IntrospectionException e) { 266 throw new MBeanException (e, "Get value for attribute: " + attr.getName()); 267 } 268 269 if (attrs.size() == 0) { 270 throw new AttributeNotFoundException ("No attribute for: " + 271 attr.getName()); 272 } 273 274 AttributeDescriptor ad = null; 275 276 for (int i = 0; i < attrs.size(); i++) { 277 ad = (AttributeDescriptor) attrs.get(i); 278 279 if ((ad.getWriteMethod() != null) && 280 ((attr.getValue() == null) || 281 ad.getWriteMethod().getParameterTypes()[0].isAssignableFrom( 282 attr.getValue().getClass()))) { 283 break; 284 } 285 } 286 287 if (ad == null) { 288 throw new AttributeNotFoundException (attr.getName()); 289 } 290 291 if (ad.getWriteMethod() == null) { 292 throw new AttributeNotFoundException ("Attribute '" + attr.getName() + 293 "' is not writable"); 294 } 295 296 try { 297 ad.getWriteMethod().invoke(_bean, new Object [] { attr.getValue() }); 298 } catch (IllegalAccessException e) { 299 throw new ReflectionException (e, 300 "Attribute '" + attr.getName() + "' is not accessible"); 301 } catch (InvocationTargetException e) { 302 Exception err; 303 304 if (e.getTargetException() instanceof Exception ) { 305 err = (Exception ) e.getTargetException(); 306 } else { 307 err = e; 308 } 309 310 throw new MBeanException (err, 311 "Error occured writing attribute: " + attr.getName()); 312 } 313 } 314 315 322 public Object invoke(String opName, Object [] params, String [] sig) 323 throws MBeanException , ReflectionException { 324 MethodInfo info = new MethodInfo(opName, sig); 325 OperationDescriptor od = (OperationDescriptor) _operations.get(info); 326 327 if (od == null) { 328 throw new MBeanException (new NullPointerException (), 329 "No action found for " + opName); 330 } 331 332 try { 333 return od.getMethod().invoke(_bean, params); 334 } catch (IllegalAccessException e) { 335 throw new ReflectionException (e, 336 "Operation '" + opName + "' is not accessible"); 337 } catch (InvocationTargetException e) { 338 throw new MBeanException (e, "Error occured peforming operation: " + 339 opName); 340 } 341 } 342 343 365 public List getAttributeDescriptorsFor(String name, String type) 366 throws IntrospectionException { 367 if (name == null) { 368 throw new IntrospectionException ("name arg cannot be null"); 369 } 370 371 List toReturn = new ArrayList (); 372 AttributeDescriptor desc; 373 Pattern namePattern = PathPattern.parse(name, true); 374 Pattern typePattern = null; 375 376 if (type != null) { 377 typePattern = PathPattern.parse(type, true); 378 } 379 380 for (Iterator iter = _attributes.values().iterator(); iter.hasNext();) { 381 desc = (AttributeDescriptor) iter.next(); 382 383 if (desc.getInfo().getType() != null) { 384 if (type != null) { 385 if (namePattern.matches(desc.getAttributeName()) && 386 typePattern.matches(desc.getType())) { 387 toReturn.add(desc); 388 } 389 } else { 390 if (namePattern.matches(desc.getAttributeName())) { 391 toReturn.add(desc); 392 } 393 } 394 } else { 395 if (namePattern.matches(desc.getAttributeName())) { 396 toReturn.add(desc); 397 } 398 } 399 } 400 401 return toReturn; 402 } 403 404 425 public void removeAttributeDescriptorsFor(String name, String type) 426 throws IntrospectionException { 427 List toRemove = getAttributeDescriptorsFor(name, type); 428 AttributeDescriptor desc; 429 430 for (int i = 0; i < toRemove.size(); i++) { 431 desc = (AttributeDescriptor) toRemove.get(i); 432 _attributes.remove(new MethodInfo(desc.getAttributeName(), 433 new String [] { desc.getType() })); 434 } 435 } 436 437 442 public void addAttributeDescriptor(AttributeDescriptor desc) { 443 _attributes.put(new MethodInfo(desc.getAttributeName(), 444 new String [] { desc.getType() }), desc); 445 } 446 447 471 public List getOperationDescriptorsFor(String name, String [] params) 472 throws IntrospectionException { 473 if (name == null) { 474 throw new IntrospectionException ("name arg cannot be null"); 475 } 476 477 List toReturn = new ArrayList (); 478 OperationDescriptor desc; 479 ParameterDescriptor paramDesc; 480 Pattern namePattern = PathPattern.parse(name, true); 481 Pattern[] typePatterns = null; 482 483 if (params != null) { 484 typePatterns = new Pattern[params.length]; 485 486 for (int i = 0; i < params.length; i++) { 487 typePatterns[i] = PathPattern.parse(params[i], false); 488 } 489 } 490 491 for (Iterator iter = _operations.values().iterator(); iter.hasNext();) { 492 desc = (OperationDescriptor) iter.next(); 493 494 if (namePattern.matches(desc.getOperationName())) { 495 if (params == null) { 496 toReturn.add(desc); 497 } else { 498 List paramList = desc.getParameters(); 499 int count = 0; 500 501 if (paramList.size() != typePatterns.length) { 502 continue; 503 } 504 505 for (int i = 0; i < paramList.size(); i++) { 506 paramDesc = (ParameterDescriptor) paramList.get(i); 507 508 if (typePatterns[i].matches(paramDesc.getInfo().getType())) { 509 count++; 510 } 511 } 512 513 if (count == params.length) { 514 toReturn.add(desc); 515 } 516 } 517 } 518 } 519 520 return toReturn; 521 } 522 523 547 public void removeOperationDescriptorsFor(String name, String [] params) 548 throws IntrospectionException { 549 List toRemove = getOperationDescriptorsFor(name, params); 550 OperationDescriptor desc; 551 552 for (int i = 0; i < toRemove.size(); i++) { 553 desc = (OperationDescriptor) toRemove.get(i); 554 _operations.remove(new MethodInfo(desc.getMethod())); 555 } 556 } 557 558 563 public void addOperationDescriptor(OperationDescriptor desc) { 564 _operations.put(new MethodInfo(desc.getMethod()), desc); 565 } 566 567 private MBeanAttributeInfo [] getAttributeInfos() 568 throws IntrospectionException { 569 MBeanAttributeInfo [] infos = new MBeanAttributeInfo [_attributes.size()]; 570 AttributeDescriptor desc; 571 int i = 0; 572 573 for (Iterator iter = _attributes.values().iterator(); iter.hasNext(); 574 i++) { 575 desc = (AttributeDescriptor) iter.next(); 576 infos[i] = desc.getInfo(); 577 } 578 579 return infos; 580 } 581 582 private MBeanOperationInfo [] getOperationInfos() { 583 MBeanOperationInfo [] infos = new MBeanOperationInfo [_operations.size()]; 584 OperationDescriptor desc; 585 int i = 0; 586 587 for (Iterator iter = _operations.values().iterator(); iter.hasNext(); 588 i++) { 589 desc = (OperationDescriptor) iter.next(); 590 infos[i] = desc.getInfo(); 591 } 592 593 return infos; 594 } 595 596 private static void initAttributeDesc(AttributeDescriptor ad, Method method) { 597 if (MethodUtils.isSetter(method)) { 598 ad.setWritable(method); 599 } else if (MethodUtils.isGetter(method)) { 600 ad.setReadable(method); 601 } 602 } 603 604 private static void initOperationDesc(OperationDescriptor od, Method method) { 605 od.setOperationName(method.getName()); 606 od.setMethod(method); 607 608 Class [] params = method.getParameterTypes(); 609 ParameterDescriptor pd; 610 String name; 611 612 for (int i = 0; i < params.length; i++) { 613 pd = new ParameterDescriptor(); 614 pd.setType(params[i].getName()); 615 pd.setName(MethodUtils.getShortClassName(params[i])); 616 od.addParameters(pd); 617 } 618 } 619 620 public void init() throws IntrospectionException { 621 _info = new MBeanInfo (_bean.getClass().getName(), _description, 622 getAttributeInfos(), new MBeanConstructorInfo [0], getOperationInfos(), 623 new MBeanNotificationInfo [0]); 624 } 625 626 public String toString() { 627 return "[ attributes=" + _attributes + ", operations=" + _operations + 628 " ]"; 629 } 630 } 631 | Popular Tags |