| 1 22 package org.jboss.mx.server; 23 24 import java.lang.reflect.Method ; 25 import java.lang.reflect.Modifier ; 26 import java.util.ArrayList ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 import javax.management.Attribute ; 33 import javax.management.AttributeList ; 34 import javax.management.AttributeNotFoundException ; 35 import javax.management.Descriptor ; 36 import javax.management.InvalidAttributeValueException ; 37 import javax.management.JMRuntimeException ; 38 import javax.management.ListenerNotFoundException ; 39 import javax.management.MBeanAttributeInfo ; 40 import javax.management.MBeanException ; 41 import javax.management.MBeanInfo ; 42 import javax.management.MBeanNotificationInfo ; 43 import javax.management.MBeanOperationInfo ; 44 import javax.management.MBeanParameterInfo ; 45 import javax.management.MBeanRegistration ; 46 import javax.management.MBeanServer ; 47 import javax.management.NotificationBroadcaster ; 48 import javax.management.NotificationEmitter ; 49 import javax.management.NotificationFilter ; 50 import javax.management.NotificationListener ; 51 import javax.management.ObjectName ; 52 import javax.management.ReflectionException ; 53 import javax.management.RuntimeErrorException ; 54 import javax.management.RuntimeMBeanException ; 55 import javax.management.RuntimeOperationsException ; 56 import javax.management.modelmbean.ModelMBeanInfo ; 57 import javax.management.modelmbean.ModelMBeanInfoSupport ; 58 59 import org.jboss.logging.Logger; 60 import org.jboss.mx.interceptor.AttributeDispatcher; 61 import org.jboss.mx.interceptor.Interceptor; 62 import org.jboss.mx.interceptor.ReflectedDispatcher; 63 import org.jboss.mx.metadata.StandardMetaData; 64 import org.jboss.mx.modelmbean.ModelMBeanConstants; 65 import org.jboss.mx.server.InvocationContext.NullDispatcher; 66 import org.jboss.mx.server.registry.MBeanEntry; 67 import org.jboss.util.Strings; 68 69 77 public abstract class AbstractMBeanInvoker 78 implements MBeanInvoker 79 { 80 83 static ThreadLocal preRegisterInfo = new ThreadLocal (); 84 85 87 90 private Object resource = null; 91 94 protected MBeanEntry resourceEntry = null; 95 96 99 protected boolean dynamicResource = true; 100 101 104 protected MBeanInfo info = null; 105 106 protected Map attributeContextMap = new HashMap (); 107 protected Map operationContextMap = new HashMap (); 108 protected Map constructorContextMap = new HashMap (); 109 110 protected InvocationContext getMBeanInfoCtx = null; 111 protected InvocationContext preRegisterCtx = null; 112 protected InvocationContext postRegisterCtx = null; 113 protected InvocationContext preDeregisterCtx = null; 114 protected InvocationContext postDeregisterCtx = null; 115 116 119 protected Logger log = Logger.getLogger(AbstractMBeanInvoker.class); 120 121 124 125 private MBeanServer server; 126 127 131 public static void setMBeanEntry(MBeanEntry entry) 132 { 133 preRegisterInfo.set(entry); 134 } 135 136 140 public static MBeanEntry getMBeanEntry() 141 { 142 return (MBeanEntry) preRegisterInfo.get(); 143 } 144 146 149 public AbstractMBeanInvoker() 150 { 151 } 152 153 156 public AbstractMBeanInvoker(Object resource) 157 { 158 this.resource = resource; 159 } 160 161 165 public AbstractMBeanInvoker(MBeanEntry resourceEntry) 166 { 167 this.resourceEntry = resourceEntry; 168 this.resource = resourceEntry.getResourceInstance(); 169 } 170 171 173 186 public Object invoke(String operationName, Object [] args, String [] signature) 187 throws MBeanException , ReflectionException  188 { 189 190 192 if (operationName == null) 193 throw new ReflectionException (new IllegalArgumentException ("Null operation name")); 194 195 String opName = operationName; 197 if (dynamicResource) 198 { 199 int dot = operationName.lastIndexOf('.'); 200 if (dot != -1) 201 { 202 if (dot < operationName.length() - 1) 203 opName = operationName.substring(dot + 1); 204 } 205 } 206 207 OperationKey key = new OperationKey(opName, signature); 209 InvocationContext ctx = (InvocationContext) operationContextMap.get(key); 210 211 if (ctx == null) 213 { 214 boolean operationExists = false; 216 if (dynamicResource) 217 { 218 for (Iterator i = operationContextMap.keySet().iterator(); i.hasNext();) 219 { 220 OperationKey thisKey = (OperationKey) i.next(); 221 if (opName.equals(thisKey.keys[0])) 222 { 223 operationExists = true; 224 break; 225 } 226 } 227 if (operationExists) 228 throw new ReflectionException (new NoSuchMethodException ("Unable to find operation " + operationName + 229 getSignatureString(signature))); 230 } 231 throw new ReflectionException (new IllegalArgumentException ("Unable to find operation " + operationName + 232 getSignatureString(signature))); 233 } 234 235 Invocation invocation = new Invocation(); 237 238 invocation.addContext(ctx); 240 241 invocation.setType(InvocationContext.OP_INVOKE); 243 244 invocation.setName(operationName); 246 247 invocation.setArgs(args); 249 250 override(invocation); 251 252 ClassLoader mbeanTCL = resourceEntry.getClassLoader(); 253 final ClassLoader ccl = TCLAction.UTIL.getContextClassLoader(); 254 boolean setCl = ccl != mbeanTCL && mbeanTCL != null; 255 if (setCl) 256 { 257 TCLAction.UTIL.setContextClassLoader(mbeanTCL); 258 } 259 260 try 261 { 262 return invocation.invoke(); 265 } 266 catch (MBeanException e) 267 { 268 throw e; 269 } 270 catch (ReflectionException e) 271 { 272 throw e; 273 } 274 catch (JMRuntimeException e) 275 { 276 throw e; 277 } 278 catch (Throwable t) 279 { 280 rethrowAsMBeanException(t); 281 return null; 282 } 283 284 finally 286 { 287 Descriptor descriptor = invocation.getDescriptor(); 288 if (descriptor != null) 289 { 290 ctx.setDescriptor(descriptor); 291 if (dynamicResource && ModelMBeanConstants.OPERATION_DESCRIPTOR.equals(descriptor.getFieldValue(ModelMBeanConstants.DESCRIPTOR_TYPE))) 292 { 293 ModelMBeanInfoSupport minfo = (ModelMBeanInfoSupport ) info; 294 minfo.setDescriptor(descriptor, ModelMBeanConstants.OPERATION_DESCRIPTOR); 295 } 296 } 297 invocation.setArgs(null); 298 invocation.setDescriptor(null); 299 invocation.setDispatcher(null); 300 301 if (setCl) 302 { 303 TCLAction.UTIL.setContextClassLoader(ccl); 304 } 305 } 306 307 } 308 309 321 public Object getAttribute(String attribute) 322 throws AttributeNotFoundException , MBeanException , ReflectionException  323 { 324 326 if (attribute == null) 327 throw new RuntimeOperationsException (new IllegalArgumentException ("Cannot get null attribute")); 328 329 InvocationContext ctx = (InvocationContext) attributeContextMap.get(attribute); 331 332 if (ctx == null) 335 throw new AttributeNotFoundException ("not found: " + attribute); 336 337 if (ctx.isReadable() == false) 338 throw new AttributeNotFoundException ("Attribute '" + attribute + "' found, but it is not readable"); 339 340 Invocation invocation = new Invocation(); 342 343 invocation.addContext(ctx); 345 346 invocation.setType(InvocationContext.OP_GETATTRIBUTE); 348 invocation.setArgs(null); 349 350 override(invocation); 351 352 ClassLoader mbeanTCL = resourceEntry.getClassLoader(); 353 final ClassLoader ccl = TCLAction.UTIL.getContextClassLoader(); 354 boolean setCl = ccl != mbeanTCL && mbeanTCL != null; 355 if (setCl) 356 { 357 TCLAction.UTIL.setContextClassLoader(mbeanTCL); 358 } 359 360 try 361 { 362 return invocation.invoke(); 363 } 364 catch (AttributeNotFoundException e) 365 { 366 throw e; 367 } 368 catch (MBeanException e) 369 { 370 throw e; 371 } 372 catch (ReflectionException e) 373 { 374 throw e; 375 } 376 catch (JMRuntimeException e) 377 { 378 throw e; 379 } 380 catch (Throwable t) 381 { 382 rethrowAsMBeanException(t); 383 return null; 384 } 385 386 finally 388 { 389 Descriptor attrDesc = invocation.getDescriptor(); 390 ctx.setDescriptor(attrDesc); 391 updateAttributeInfo(attrDesc); 392 393 if (setCl) 394 { 395 TCLAction.UTIL.setContextClassLoader(ccl); 396 } 397 } 398 } 399 400 413 public void setAttribute(Attribute attribute) throws AttributeNotFoundException , 414 InvalidAttributeValueException , MBeanException , ReflectionException  415 { 416 418 if (attribute == null) 419 throw new InvalidAttributeValueException ("null attribute"); 420 421 String name = attribute.getName(); 423 InvocationContext ctx = (InvocationContext) attributeContextMap.get(name); 424 425 if (ctx == null) 428 throw new AttributeNotFoundException ("not found: " + name); 429 else if (ctx.isWritable() == false) 430 { 431 throw new AttributeNotFoundException ("Attribute '" + name 432 + "' is not writable"); 433 } 434 435 Invocation invocation = new Invocation(); 437 438 invocation.addContext(ctx); 440 441 invocation.setType(InvocationContext.OP_SETATTRIBUTE); 443 444 invocation.setArgs(new Object []{attribute.getValue()}); 446 447 override(invocation); 448 449 ClassLoader mbeanTCL = resourceEntry.getClassLoader(); 450 final ClassLoader ccl = TCLAction.UTIL.getContextClassLoader(); 451 boolean setCl = ccl != mbeanTCL && mbeanTCL != null; 452 if (setCl) 453 { 454 TCLAction.UTIL.setContextClassLoader(mbeanTCL); 455 } 456 457 try 458 { 459 invocation.invoke(); 462 } 463 catch (AttributeNotFoundException e) 464 { 465 throw e; 466 } 467 catch (InvalidAttributeValueException e) 468 { 469 throw e; 470 } 471 catch (MBeanException e) 472 { 473 throw e; 474 } 475 catch (ReflectionException e) 476 { 477 throw e; 478 } 479 catch (JMRuntimeException e) 480 { 481 throw e; 482 } 483 catch (Throwable t) 484 { 485 rethrowAsMBeanException(t); 486 } 487 488 finally 490 { 491 495 Descriptor attrDesc = invocation.getDescriptor(); 496 ctx.setDescriptor(attrDesc); 497 updateAttributeInfo(attrDesc); 498 499 if (setCl) 500 { 501 TCLAction.UTIL.setContextClassLoader(ccl); 502 } 503 } 504 } 505 506 public MBeanInfo getMBeanInfo() 507 { 508 Invocation invocation = new Invocation(getMBeanInfoCtx); 510 511 invocation.setType(InvocationContext.OP_GETMBEANINFO); 513 514 if (resourceEntry == null) 515 resourceEntry = getMBeanEntry(); 516 ClassLoader mbeanTCL = resourceEntry.getClassLoader(); 517 final ClassLoader ccl = TCLAction.UTIL.getContextClassLoader(); 518 boolean setCl = ccl != mbeanTCL && mbeanTCL != null; 519 if (setCl) 520 { 521 TCLAction.UTIL.setContextClassLoader(mbeanTCL); 522 } 523 524 try 525 { 526 MBeanInfo info = (MBeanInfo ) invocation.invoke(); 527 return info; 528 } 529 catch (JMRuntimeException e) 530 { 531 throw e; 532 } 533 catch (Throwable t) 534 { 535 rethrowAsRuntimeMBeanException(t); 536 return null; 537 } 538 finally 539 { 540 if (setCl) 541 { 542 TCLAction.UTIL.setContextClassLoader(ccl); 543 } 544 } 545 } 546 547 public AttributeList getAttributes(java.lang.String [] attributes) 548 { 549 if (attributes == null) 550 throw new IllegalArgumentException ("null array"); 551 552 AttributeList list = new AttributeList (); 553 554 for (int i = 0; i < attributes.length; ++i) 555 { 556 try 557 { 558 list.add(new Attribute (attributes[i], getAttribute(attributes[i]))); 559 } 560 catch (Throwable ignored) 561 { 562 } 564 } 565 566 return list; 567 } 568 569 public AttributeList setAttributes(AttributeList attributes) 570 { 571 if (attributes == null) 572 throw new IllegalArgumentException ("null list"); 573 574 AttributeList results = new AttributeList (); 575 Iterator it = attributes.iterator(); 576 577 while (it.hasNext()) 578 { 579 Attribute attr = (Attribute ) it.next(); 580 try 581 { 582 setAttribute(attr); 583 results.add(attr); 584 } 585 catch (Throwable ignored) 586 { 587 if (log.isTraceEnabled()) 589 log.trace("Unhandled setAttribute() for attribute: " + attr.getName(), ignored); 590 } 591 } 592 593 return results; 594 } 595 596 597 599 608 public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception  609 { 610 this.resourceEntry = (MBeanEntry) preRegisterInfo.get(); 611 this.server = server; 612 613 ObjectName mbeanName = null; 614 Descriptor mbeanDescriptor = null; 615 if( info instanceof ModelMBeanInfo ) 616 { 617 ModelMBeanInfo minfo = (ModelMBeanInfo ) info; 618 try 619 { 620 mbeanDescriptor = minfo.getDescriptor("", 621 ModelMBeanConstants.MBEAN_DESCRIPTOR); 622 String type = (String ) mbeanDescriptor.getFieldValue( 623 ModelMBeanConstants.MBEAN_SERVER_INJECTION_TYPE); 624 if( type != null ) 625 { 626 inject(ModelMBeanConstants.MBEAN_SERVER_INJECTION_TYPE, 627 type, MBeanServer .class, getServer()); 628 } 629 } 630 catch (MBeanException e) 631 { 632 log.warn("Failed to obtain descriptor: "+ModelMBeanConstants.MBEAN_DESCRIPTOR, e); 633 } 634 635 } 636 637 ClassLoader mbeanTCL = resourceEntry.getClassLoader(); 638 final ClassLoader ccl = TCLAction.UTIL.getContextClassLoader(); 639 boolean setCl = ccl != mbeanTCL && mbeanTCL != null; 640 if (setCl) 641 { 642 TCLAction.UTIL.setContextClassLoader(mbeanTCL); 643 } 644 645 try 646 { 647 initAttributeContexts(info.getAttributes()); 648 649 initOperationContexts(info.getOperations()); 650 651 if (resource != null) 652 initDispatchers(); 653 654 mbeanName = invokePreRegister(server, name); 655 if( mbeanDescriptor != null ) 656 { 657 Object value = mbeanDescriptor.getFieldValue( 658 ModelMBeanConstants.OBJECT_NAME_INJECTION_TYPE); 659 String type = (String ) value; 660 if( type != null ) 661 { 662 inject(ModelMBeanConstants.OBJECT_NAME_INJECTION_TYPE, 663 type, ObjectName .class, mbeanName); 664 } 665 } 666 } 667 finally 668 { 669 if (setCl) 670 { 671 TCLAction.UTIL.setContextClassLoader(ccl); 672 } 673 } 674 return mbeanName; 675 } 676 677 679 public void postRegister(Boolean registrationSuccessful) 680 { 681 invokePostRegister(registrationSuccessful); 682 } 683 684 686 public void preDeregister() throws Exception  687 { 688 invokePreDeregister(); 689 } 690 691 693 public void postDeregister() 694 { 695 invokePostDeregister(); 696 this.server = null; 697 } 698 699 700 702 public void addNotificationListener(NotificationListener listener, 703 NotificationFilter filter, Object handback) 704 { 705 addNotificationListenerToResource(listener, filter, handback); 706 } 707 708 protected void addNotificationListenerToResource(NotificationListener listener, NotificationFilter filter, Object handback) 709 { 710 if (resource instanceof NotificationBroadcaster ) 711 { 712 ((NotificationBroadcaster ) resource).addNotificationListener(listener, filter, handback); 713 } 714 else 715 { 716 throw new RuntimeMBeanException (new IllegalArgumentException ("Target XXX is not a notification broadcaster" 717 718 )); 720 } 721 } 722 723 public void removeNotificationListener(NotificationListener listener) 724 throws ListenerNotFoundException  725 { 726 removeNotificationListenerFromResource(listener); 727 } 728 729 protected void removeNotificationListenerFromResource(NotificationListener listener) 730 throws ListenerNotFoundException  731 { 732 if (resource instanceof NotificationBroadcaster ) 733 { 734 ((NotificationBroadcaster ) resource).removeNotificationListener(listener); 735 } 736 else 737 { 738 throw new RuntimeMBeanException (new IllegalArgumentException ("Target XXX is not a notification broadcaster" 739 740 )); 742 } 743 } 744 745 public void removeNotificationListener(NotificationListener listener, 746 NotificationFilter filter, 747 Object handback) 748 throws ListenerNotFoundException  749 { 750 removeNotificationListenerFromResource(listener, filter, handback); 751 } 752 753 protected void removeNotificationListenerFromResource(NotificationListener listener, 754 NotificationFilter filter, 755 Object handback) 756 throws ListenerNotFoundException  757 { 758 if (resource instanceof NotificationEmitter ) 759 { 760 ((NotificationEmitter ) resource).removeNotificationListener(listener, filter, handback); 761 } 762 else if (resource instanceof NotificationBroadcaster ) 763 { 764 removeNotificationListener(listener); 769 } 770 else 771 { 772 throw new RuntimeMBeanException (new IllegalArgumentException ("Target XXX is not a notification emitter" 773 774 )); 776 } 777 } 778 779 public MBeanNotificationInfo [] getNotificationInfo() 780 { 781 return getNotificationInfoFromResource(); 782 } 783 784 protected MBeanNotificationInfo [] getNotificationInfoFromResource() 785 { 786 if (resource instanceof NotificationBroadcaster ) 787 { 788 return ((NotificationBroadcaster ) resource).getNotificationInfo(); 789 } 790 else 791 return new MBeanNotificationInfo []{}; 792 } 793 794 795 797 public MBeanInfo getMetaData() 798 { 799 return info; 800 } 801 802 public Object getResource() 803 { 804 return resource; 805 } 806 807 815 public void setResource(Object resource) 816 {
|