1 22 package org.jboss.mx.modelmbean; 23 24 import java.beans.BeanInfo ; 25 import java.beans.IntrospectionException ; 26 import java.beans.Introspector ; 27 import java.beans.PropertyDescriptor ; 28 import java.beans.PropertyEditor ; 29 import java.beans.PropertyEditorManager ; 30 import java.lang.reflect.Constructor ; 31 import java.lang.reflect.Method ; 32 import java.util.ArrayList ; 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Map ; 37 38 import javax.management.Attribute ; 39 import javax.management.AttributeChangeNotification ; 40 import javax.management.AttributeChangeNotificationFilter ; 41 import javax.management.Descriptor ; 42 import javax.management.InstanceNotFoundException ; 43 import javax.management.JMException ; 44 import javax.management.ListenerNotFoundException ; 45 import javax.management.MBeanAttributeInfo ; 46 import javax.management.MBeanException ; 47 import javax.management.MBeanInfo ; 48 import javax.management.MBeanNotificationInfo ; 49 import javax.management.MBeanOperationInfo ; 50 import javax.management.MBeanServer ; 51 import javax.management.Notification ; 52 import javax.management.NotificationFilter ; 53 import javax.management.NotificationListener ; 54 import javax.management.ObjectName ; 55 import javax.management.RuntimeErrorException ; 56 import javax.management.RuntimeOperationsException ; 57 import javax.management.modelmbean.InvalidTargetObjectTypeException ; 58 import javax.management.modelmbean.ModelMBean ; 59 import javax.management.modelmbean.ModelMBeanAttributeInfo ; 60 import javax.management.modelmbean.ModelMBeanInfo ; 61 import javax.management.modelmbean.ModelMBeanInfoSupport ; 62 import javax.management.modelmbean.ModelMBeanOperationInfo ; 63 64 import org.jboss.logging.Logger; 65 import org.jboss.mx.interceptor.AbstractInterceptor; 66 import org.jboss.mx.interceptor.Interceptor; 67 import org.jboss.mx.interceptor.ModelMBeanAttributeInterceptor; 68 import org.jboss.mx.interceptor.ModelMBeanInfoInterceptor; 69 import org.jboss.mx.interceptor.ModelMBeanInterceptor; 70 import org.jboss.mx.interceptor.ModelMBeanOperationInterceptor; 71 import org.jboss.mx.interceptor.NullInterceptor; 72 import org.jboss.mx.interceptor.ObjectReferenceInterceptor; 73 import org.jboss.mx.interceptor.PersistenceInterceptor; 74 import org.jboss.mx.interceptor.PersistenceInterceptor2; 75 import org.jboss.mx.persistence.NullPersistence; 76 import org.jboss.mx.persistence.PersistenceManager; 77 import org.jboss.mx.server.AbstractMBeanInvoker; 78 import org.jboss.mx.server.Invocation; 79 import org.jboss.mx.server.InvocationContext; 80 import org.jboss.mx.server.MBeanInvoker; 81 import org.jboss.mx.util.JBossNotificationBroadcasterSupport; 82 83 96 public abstract class ModelMBeanInvoker extends AbstractMBeanInvoker 97 implements ModelMBean , ModelMBeanConstants 98 { 99 Logger log = Logger.getLogger(ModelMBeanInvoker.class.getName()); 100 101 103 111 protected String resourceType = null; 112 113 116 protected PersistenceManager persistence = new NullPersistence(); 117 118 121 protected JBossNotificationBroadcasterSupport notifier = new JBossNotificationBroadcasterSupport(); 122 123 126 protected long notifierSequence = 1; 127 128 131 protected long attrNotifierSequence = 1; 132 133 134 136 139 public ModelMBeanInvoker() 140 { 141 } 142 143 149 public ModelMBeanInvoker(ModelMBeanInfo info) throws MBeanException 150 { 151 setModelMBeanInfo(info); 152 } 153 154 155 156 158 163 public void setModelMBeanInfo(ModelMBeanInfo info) 164 throws MBeanException , RuntimeOperationsException 165 { 166 if (info == null) 167 throw new RuntimeOperationsException (new IllegalArgumentException ("MBeanInfo cannot be null")); 168 169 this.info = new ModelMBeanInfoSupport (info); 171 172 ModelMBeanInfo minfo = info; 174 Descriptor mbeanDescriptor = null; 175 try 176 { 177 mbeanDescriptor = minfo.getDescriptor("", 178 ModelMBeanConstants.MBEAN_DESCRIPTOR); 179 } 180 catch (MBeanException e) 181 { 182 log.warn("Failed to obtain descriptor: "+ModelMBeanConstants.MBEAN_DESCRIPTOR, e); 183 return; 184 } 185 186 String type = (String ) mbeanDescriptor.getFieldValue( 187 ModelMBeanConstants.MBEAN_INFO_INJECTION_TYPE); 188 if( type != null ) 189 { 190 inject(ModelMBeanConstants.MBEAN_INFO_INJECTION_TYPE, 191 type, MBeanInfo .class, info); 192 } 193 } 194 195 203 public void setManagedResource(Object ref, String resourceType) 204 throws MBeanException , InstanceNotFoundException , InvalidTargetObjectTypeException 205 { 206 if (!isSupportedResourceType(ref, resourceType)) 207 throw new InvalidTargetObjectTypeException ("Unsupported resource type: " + resourceType); 208 209 setResource(ref); 210 this.resourceType = resourceType; 211 212 if (getServer() != null) 213 { 214 try 215 { 216 this.init(getServer(), resourceEntry.getObjectName()); 217 } 218 catch(Exception e) 219 { 220 throw new MBeanException (e, "Failed to init from resource"); 221 } 222 } 223 } 224 225 227 public void addNotificationListener(NotificationListener listener, 228 NotificationFilter filter, 229 Object handback) 230 { 231 notifier.addNotificationListener(listener, filter, handback); 232 } 233 234 public void removeNotificationListener(NotificationListener listener) 235 throws ListenerNotFoundException 236 { 237 notifier.removeNotificationListener(listener); 238 } 239 240 public void removeNotificationListener(NotificationListener listener, 241 NotificationFilter filter, 242 Object handback) 243 throws ListenerNotFoundException 244 { 245 notifier.removeNotificationListener(listener, filter, handback); 246 } 247 248 255 public void sendNotification(String ntfyText) 256 throws MBeanException , RuntimeOperationsException 257 { 258 if( ntfyText == null ) 259 { 260 throw new RuntimeOperationsException ( 261 new IllegalArgumentException ("ntfyText cannot be null") 262 ); 263 } 264 Notification notif = new Notification ( 265 GENERIC_MODELMBEAN_NOTIFICATION, this, 1, ntfyText ); 270 271 sendNotification(notif); 272 } 273 274 279 public void sendNotification(Notification ntfyObj) 280 throws MBeanException , RuntimeOperationsException 281 { 282 if( ntfyObj == null ) 283 { 284 throw new RuntimeOperationsException ( 285 new IllegalArgumentException ("ntfyText cannot be null") 286 ); 287 } 288 notifier.sendNotification(ntfyObj); 289 } 290 291 296 public void sendAttributeChangeNotification(AttributeChangeNotification notification) 297 throws MBeanException 298 { 299 if( notification == null ) 300 { 301 throw new RuntimeOperationsException ( 302 new IllegalArgumentException ("notification cannot be null") 303 ); 304 } 305 notifier.sendNotification(notification); 306 } 307 308 317 public void sendAttributeChangeNotification(Attribute oldValue, Attribute newValue) 318 throws MBeanException , RuntimeOperationsException 319 { 320 if( oldValue == null || newValue == null ) 321 { 322 throw new RuntimeOperationsException ( 323 new IllegalArgumentException ("Attribute cannot be null") 324 ); 325 } 326 if (!(oldValue.getName().equals(newValue.getName()))) 327 { 328 throw new RuntimeOperationsException ( 329 new IllegalArgumentException ("Attribute name mismatch between oldvalue and newvalue") 330 ); 331 } 332 333 String attr = oldValue.getName(); 334 String type = ((ModelMBeanInfo ) info).getAttribute(attr).getType(); 335 336 AttributeChangeNotification notif = new AttributeChangeNotification ( 337 this, 1, System.currentTimeMillis(), "" + attr + " changed from " + oldValue + " to " + newValue, 341 attr, type, oldValue.getValue(), 343 newValue.getValue() ); 345 346 notifier.sendNotification(notif); 347 } 348 349 public MBeanNotificationInfo [] getNotificationInfo() 350 { 351 return info.getNotifications(); 352 } 353 354 356 public void addAttributeChangeNotificationListener( 357 NotificationListener listener, 358 String attributeName, 359 Object handback) throws MBeanException 360 { 361 ModelMBeanInfo minfo = (ModelMBeanInfo ) info; 363 AttributeChangeNotificationFilter filter = null; 364 if (attributeName != null) 365 { 366 ModelMBeanAttributeInfo ainfo = minfo.getAttribute(attributeName); 367 if( ainfo == null ) 368 { 369 throw new RuntimeOperationsException ( 370 new IllegalArgumentException ("Attribute does not exist: "+attributeName)); 371 } 372 filter = new AttributeChangeNotificationFilter (); 373 filter.enableAttribute(attributeName); 374 } 375 else 376 { 377 filter = new AttributeChangeNotificationFilter (); 378 MBeanAttributeInfo [] allAttributes = minfo.getAttributes(); 379 for (int i = 0; i < allAttributes.length; ++i) 380 filter.enableAttribute(allAttributes[i].getName()); 381 } 382 notifier.addNotificationListener(listener, filter, handback); 383 } 384 385 387 public void removeAttributeChangeNotificationListener( 388 NotificationListener listener, 389 String attributeName) throws MBeanException , ListenerNotFoundException 390 { 391 if( attributeName != null ) 392 { 393 ModelMBeanInfo minfo = (ModelMBeanInfo ) info; 395 ModelMBeanAttributeInfo ainfo = minfo.getAttribute(attributeName); 396 if( ainfo == null ) 397 { 398 throw new RuntimeOperationsException ( 399 new IllegalArgumentException ("Attribute does not exist: "+attributeName)); 400 } 401 } 402 notifier.removeNotificationListener(listener); 403 } 404 405 public void load() throws MBeanException , InstanceNotFoundException 407 { 408 if (info == null) 409 return; 410 411 persistence.load(this, info); 412 } 413 414 public void store() throws MBeanException , InstanceNotFoundException 415 { 416 persistence.store(info); 417 } 418 419 420 422 435 public ObjectName invokePreRegister(MBeanServer server, ObjectName name) 436 throws Exception 437 { 438 if (info == null) 441 { 442 throw new RuntimeErrorException ( 443 new Error ("MBeanInfo has not been set.")); 444 } 445 446 final ModelMBeanInfo minfo = (ModelMBeanInfo ) info; 448 Descriptor mbeanDescriptor = minfo.getMBeanDescriptor(); 449 getMBeanInfoCtx = new InvocationContext(); 450 getMBeanInfoCtx.setInvoker(this); 451 getMBeanInfoCtx.setDescriptor(mbeanDescriptor); 452 getMBeanInfoCtx.setDispatcher(new AbstractInterceptor("MBeanInfo Dispatcher") 453 { 454 public Object invoke(Invocation invocation) throws Throwable 455 { 456 return minfo; 457 } 458 }); 459 463 String [] signature = new String []{"java.lang.Object", "java.lang.String"}; 466 OperationKey opKey = new OperationKey("setManagedResource", signature); 467 InvocationContext ctx = new InvocationContext(); 468 ctx.setInvoker(this); 469 ctx.setDispatcher(new AbstractInterceptor("SetMangedResource Dispatcher") 470 { 471 public Object invoke(Invocation invocation) throws Throwable 472 { 473 Object [] args = invocation.getArgs(); 474 setManagedResource(args[0], (String ) args[1]); 475 return null; 476 } 477 }); 478 operationContextMap.put(opKey, ctx); 479 480 if (getResource() == null ) 481 { 482 return name; 483 } 484 else 485 { 486 init(server, name); 487 } 488 489 return super.invokePreRegister(server, name); 490 } 491 492 494 500 protected void init(MBeanServer server, ObjectName name) 501 throws Exception 502 { 503 ModelMBeanInfo minfo = (ModelMBeanInfo ) info; 504 configureInterceptorStack(minfo, server, name); 505 initDispatchers(); 506 507 Object resource = getResource(); 509 if (resource != null) 510 { 511 Descriptor mbeanDescriptor = minfo.getMBeanDescriptor(); 512 String resClassName = getResource().getClass().getName(); 513 mbeanDescriptor.setField(ModelMBeanConstants.RESOURCE_CLASS, resClassName); 514 minfo.setMBeanDescriptor(mbeanDescriptor); 515 } 516 517 setValuesFromMBeanInfo(); 519 520 initPersistence(server, name); 521 522 load(); 524 } 525 526 530 protected void initPersistence(MBeanServer server, ObjectName name) 531 throws MBeanException , InstanceNotFoundException 532 { 533 Descriptor [] descriptors; 534 ModelMBeanInfo minfo = (ModelMBeanInfo ) getMetaData(); 535 536 try 537 { 538 descriptors = minfo.getDescriptors(MBEAN_DESCRIPTOR); 539 } 540 catch (MBeanException e) 541 { 542 log.error("Failed to obtain MBEAN_DESCRIPTORs", e); 543 return; 544 } 545 546 if (descriptors == null) 547 { 548 return; 549 } 550 String persistMgrName = null; 551 for (int i = 0; ((i < descriptors.length) && (persistMgrName == null)); i++) 552 { 553 persistMgrName = (String ) descriptors[i].getFieldValue(PERSISTENCE_MANAGER); 554 } 555 if (persistMgrName == null) 556 { 557 log.trace("No " + PERSISTENCE_MANAGER 558 + " descriptor found, null persistence will be used"); 559 return; 560 } 561 562 try 563 { 564 persistence = (PersistenceManager) server.instantiate(persistMgrName); 565 log.debug("Loaded persistence mgr: " + persistMgrName); 566 567 Descriptor descriptor = minfo.getMBeanDescriptor(); 570 descriptor.setField(ModelMBeanConstants.OBJECT_NAME, name); 571 minfo.setMBeanDescriptor(descriptor); 572 } 573 catch (Exception cause) 574 { 575 log.error("Unable to instantiate the persistence manager:" 576 + persistMgrName, cause); 577 } 578 } 579 580 protected void initOperationContexts(MBeanOperationInfo [] operations) 581 { 582 super.initOperationContexts(operations); 584 585 for (int i = 0; i < operations.length; ++i) 586 { 587 OperationKey key = new OperationKey(operations[i]); 588 589 InvocationContext ctx = (InvocationContext) operationContextMap.get(key); 590 ModelMBeanOperationInfo info = (ModelMBeanOperationInfo ) operations[i]; 591 ctx.setDescriptor(info.getDescriptor()); 592 } 593 } 594 595 protected void initAttributeContexts(MBeanAttributeInfo [] attributes) 596 { 597 super.initAttributeContexts(attributes); 598 599 for (int i = 0; i < attributes.length; ++i) 600 { 601 ModelMBeanAttributeInfo info = (ModelMBeanAttributeInfo ) attributes[i]; 602 String name = info.getName(); 603 InvocationContext ctx = (InvocationContext) attributeContextMap.get(name); 604 ctx.setDescriptor(info.getDescriptor()); 605 ctx.setReadable(info.isReadable()); 606 ctx.setWritable(info.isWritable()); 607 } 608 } 609 610 619 protected void configureInterceptorStack(ModelMBeanInfo info, MBeanServer server, ObjectName name) 620 throws Exception 621 { 622 627 List defaultInterceptors = getInterceptors(getMBeanInfoCtx.getDescriptor()); 628 629 List interceptors = null; 630 if (defaultInterceptors != null) 631 { 632 interceptors = new ArrayList (defaultInterceptors); 633 } 634 if (interceptors == null) 635 { 636 interceptors = getMBeanInfoCtx.getInterceptors(); 638 } 639 643 String mbeanName = name != null ? name.toString() : info.getClassName(); 644 interceptors.add(new ModelMBeanInfoInterceptor(mbeanName)); 645 getMBeanInfoCtx.setInterceptors(interceptors); 646 647 for (Iterator it = attributeContextMap.entrySet().iterator(); it.hasNext();) 649 { 650 Map.Entry entry = (Map.Entry ) it.next(); 651 652 InvocationContext ctx = (InvocationContext) entry.getValue(); 653 List list = getInterceptors(ctx.getDescriptor()); 654 if (list == null) 655 { 656 if (defaultInterceptors != null) 658 { 659 list = new ArrayList (defaultInterceptors); 660 } 661 else 662 { 663 list = new ArrayList (); 664 } 665 } 666 list.add(new PersistenceInterceptor()); 668 list.add(new ModelMBeanAttributeInterceptor()); 669 ctx.setInterceptors(list); 670 } 671 672 for (Iterator it = operationContextMap.entrySet().iterator(); it.hasNext();) 674 { 675 Map.Entry entry = (Map.Entry ) it.next(); 676 677 InvocationContext ctx = (InvocationContext) entry.getValue(); 678 List list = getInterceptors(ctx.getDescriptor()); 679 if (list == null && defaultInterceptors != null) 680 list = new ArrayList (defaultInterceptors); 681 682 if (dynamicResource) 684 { 685 if (list == null) 686 { 687 list = new ArrayList (); 688 } 689 list.add(new ModelMBeanOperationInterceptor()); 690 } 691 692 if (list != null) 693 { 694 698 list.add(new NullInterceptor()); 699 ctx.setInterceptors(list); 700 } 701 } 702 } 703 704 710 protected List getInterceptors(Descriptor d) throws Exception 711 { 712 if (d == null) 713 return null; 714 Descriptor [] interceptorDescriptors = (Descriptor []) d.getFieldValue(INTERCEPTORS); 715 if (interceptorDescriptors == null) 716 return null; 717 718 ArrayList interceptors = new ArrayList (); 719 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 720 for (int i = 0; i < interceptorDescriptors.length; i++) 721 { 722 Descriptor desc = interceptorDescriptors[i]; 723 String code = (String ) desc.getFieldValue("code"); 724 if (code.equals(ModelMBeanInterceptor.class.getName()) || 726 code.equals(ObjectReferenceInterceptor.class.getName()) || 727 code.equals(PersistenceInterceptor2.class.getName())) 728 { 729 log.debug("Ignoring obsolete legacy interceptor: " + code); 730 continue; 731 } 732 733 Class interceptorClass = loader.loadClass(code); 734 Interceptor interceptor = null; 735 Class [] ctorSig = {MBeanInvoker.class}; 737 try 738 { 739 Constructor ctor = interceptorClass.getConstructor(ctorSig); 740 Object [] ctorArgs = {this}; 741 interceptor = (Interceptor) ctor.newInstance(ctorArgs); 742 } 743 catch (Throwable t) 744 { 745 log.debug("Could not invoke CTOR(MBeanInvoker) for '" 746 + interceptorClass + "', trying default CTOR: " + t.getMessage()); 747 748 interceptor = (Interceptor) interceptorClass.newInstance(); 750 } 751 interceptors.add(interceptor); 752 753 String [] names = desc.getFieldNames(); 755 HashMap propertyMap = new HashMap (); 756 if (names.length > 1) 757 { 758 BeanInfo beanInfo = Introspector.getBeanInfo(interceptorClass); 759 PropertyDescriptor [] props = beanInfo.getPropertyDescriptors(); 760 for (int p = 0; p < props.length; p++) 761 { 762 String fieldName = props[p].getName(); 763 propertyMap.put(fieldName, props[p]); 764 } 765 for (int n = 0; n < names.length; n++) 767 { 768 String name = names[n]; 769 if (name.equals("code")) 770 continue; 771 String text = (String ) desc.getFieldValue(name); 772 PropertyDescriptor pd = (PropertyDescriptor ) propertyMap.get(name); 773 if (pd == null) 774 throw new IntrospectionException ("No PropertyDescriptor for attribute:" + name); 775 Method setter = pd.getWriteMethod(); 776 if (setter != null) 777 { 778 Class ptype = pd.getPropertyType(); 779 PropertyEditor editor = PropertyEditorManager.findEditor(ptype); 780 if (editor == null) 781 throw new IntrospectionException ("Cannot convert string to interceptor attribute:" + name); 782 editor.setAsText(text); 783 Object args[] = {editor.getValue()}; 784 setter.invoke(interceptor, args); 785 } 786 } 787 } 788 } 789 790 if (interceptors.size() == 0) 791 interceptors = null; 792 return interceptors; 793 } 794 795 protected void setValuesFromMBeanInfo() throws JMException 796 { 797 for (Iterator it = attributeContextMap.entrySet().iterator(); it.hasNext();) 798 { 799 Map.Entry entry = (Map.Entry ) it.next(); 800 String key = (String ) entry.getKey(); 801 802 InvocationContext ctx = (InvocationContext) entry.getValue(); 803 Object value = ctx.getDescriptor().getFieldValue(XMBeanConstants.CACHED_VALUE); 805 if (value != null) 806 { 807 setAttribute(new Attribute (key, value)); 808 } } 810 811 } 812 813 protected boolean isSupportedResourceType(Object resource, String resourceType) 814 { 815 if (resourceType.equalsIgnoreCase(OBJECT_REF)) 816 return true; 817 818 return false; 819 } 820 821 protected void override(Invocation invocation) throws MBeanException 822 { 823 if (dynamicResource && info != null) 825 { 826 Descriptor current = invocation.getDescriptor(); 827 if (current != null) 828 { 829 ModelMBeanInfo mminfo = (ModelMBeanInfo ) info; 830 Descriptor descriptor = mminfo.getDescriptor((String ) current.getFieldValue(NAME), (String ) current.getFieldValue(DESCRIPTOR_TYPE)); 831 if (descriptor != null) 832 invocation.setDescriptor(descriptor); 833 } 834 } 835 } 836 837 } 838 839 | Popular Tags |