1 17 18 package org.sape.carbon.services.management.interceptor; 19 20 import java.beans.BeanInfo ; 21 import java.beans.Introspector ; 22 import java.beans.PropertyDescriptor ; 23 import java.lang.reflect.InvocationTargetException ; 24 import java.lang.reflect.Method ; 25 import java.lang.reflect.Proxy ; 26 import java.rmi.dgc.VMID ; 27 import java.util.ArrayList ; 28 import java.util.Collections ; 29 import java.util.Comparator ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 33 import javax.management.Attribute ; 34 import javax.management.AttributeList ; 35 import javax.management.AttributeNotFoundException ; 36 import javax.management.InstanceAlreadyExistsException ; 37 import javax.management.InvalidAttributeValueException ; 38 import javax.management.MBeanAttributeInfo ; 39 import javax.management.MBeanConstructorInfo ; 40 import javax.management.MBeanException ; 41 import javax.management.MBeanFeatureInfo ; 42 import javax.management.MBeanInfo ; 43 import javax.management.MBeanNotificationInfo ; 44 import javax.management.MBeanOperationInfo ; 45 import javax.management.MBeanParameterInfo ; 46 import javax.management.MBeanRegistrationException ; 47 import javax.management.MBeanServer ; 48 import javax.management.MalformedObjectNameException ; 49 import javax.management.NotCompliantMBeanException ; 50 import javax.management.Notification ; 51 import javax.management.NotificationBroadcaster ; 52 import javax.management.NotificationBroadcasterSupport ; 53 import javax.management.ObjectName ; 54 import javax.management.ReflectionException ; 55 56 import org.sape.carbon.core.component.Component; 57 import org.sape.carbon.core.component.ComponentConfiguration; 58 import org.sape.carbon.core.component.Lookup; 59 import org.sape.carbon.core.component.event.ComponentEvent; 60 import org.sape.carbon.core.component.event.EventManager; 61 import org.sape.carbon.core.component.lifecycle.LifecycleInterceptor; 62 import org.sape.carbon.core.component.proxy.Interceptor; 63 import org.sape.carbon.core.component.proxy.Invocation; 64 import org.sape.carbon.core.config.Config; 65 import org.sape.carbon.core.config.InvalidConfigurationException; 66 import org.sape.carbon.core.exception.ExceptionUtility; 67 import org.sape.carbon.core.util.reflection.BeanUtil; 68 import org.sape.carbon.core.util.reflection.ClassTree; 69 import org.sape.carbon.services.jmx.server.MBeanServerRetreiveException; 70 import org.sape.carbon.services.jmx.server.MBeanServerService; 71 72 import org.apache.commons.logging.Log; 73 import org.apache.commons.logging.LogFactory; 74 75 103 public class DefaultManagementInterceptorImpl 104 extends NotificationBroadcasterSupport 105 implements ManagementInterceptor, Interceptor, EventManager { 106 107 108 private Log log = LogFactory.getLog(this.getClass()); 109 110 113 private long notificationSequence = 0L; 114 115 119 protected Component component; 120 121 125 protected ObjectName objectName; 126 127 133 protected MBeanInfo mBeanInfo = null; 134 135 138 protected Interceptor nextInterceptor; 139 140 144 private static final String PROPERTY_NAME = "name="; 145 146 147 private static final String PROPERTY_TYPE = ",type="; 148 149 150 private static final String PROPERTY_ENVIRONMENT = ",environment="; 151 152 153 private static final String PROPERTY_INSTANCE = ",instance="; 154 155 156 private static final String PROPERTY_VMID = ",vmid="; 157 158 159 private static final String UNIQUE_ID; 160 161 162 private String mbeanServerServiceName; 163 164 165 private boolean shouldSendNotifications; 166 167 168 private ManagementInterceptorConfiguration config; 169 170 171 private Class componentFunctionalInterface; 172 173 174 public static final String METADATA_CONFIG_LOCATION = "/manage/info/"; 175 176 static { 177 String id = new VMID ().toString(); 178 UNIQUE_ID = id.replace(':', '-'); 179 } 180 181 189 public DefaultManagementInterceptorImpl( 190 ManagementInterceptorConfiguration config, 191 Class componentFunctionalInterface) { 192 193 this.mbeanServerServiceName = 194 config.getMBeanServerServiceLocation(); 195 196 this.shouldSendNotifications = config.isSendNotifications(); 197 198 this.config = config; 199 200 this.componentFunctionalInterface = componentFunctionalInterface; 201 202 } 203 204 209 public void setNextInterceptor(Interceptor interceptor) { 210 this.nextInterceptor = interceptor; 211 } 212 213 214 228 public Object getAttribute(String attribute) 229 throws AttributeNotFoundException , MBeanException , ReflectionException { 230 231 try { 232 return BeanUtil.getObjectAttribute(this.component, attribute); 233 } catch (IllegalAccessException iae) { 234 throw new ReflectionException (iae); 235 } catch (InvocationTargetException ite) { 236 throw new ReflectionException (ite); 237 } catch (IllegalArgumentException iae) { 238 throw new ReflectionException (iae); 239 } catch (NoSuchMethodException nsme) { 240 throw new ReflectionException (nsme); 241 } 242 } 243 244 245 252 public AttributeList getAttributes(String [] attributes) { 253 AttributeList list = new AttributeList (); 254 255 for (int i = 0; i < attributes.length; i++) { 256 Object value = null; 257 try { 258 value = this.getAttribute(attributes[i]); 259 } catch (Exception e) { 260 } 262 list.add(new Attribute (attributes[i], value)); 263 } 264 return list; 265 } 266 267 268 277 public MBeanInfo getMBeanInfo() { 278 synchronized (this) { 279 if (this.mBeanInfo == null) { 280 this.mBeanInfo = buildMBeanInfo(this.component); 281 } 282 } 283 return this.mBeanInfo; 284 } 285 286 291 public Class getComponentType() { 292 return this.component.getClass(); 293 } 294 295 315 protected MBeanInfo buildMBeanInfo(Component component) { 316 317 String name = this.component.getComponentName(); 318 319 if (log.isTraceEnabled()) { 320 log.trace( 321 "Building MBeanInfo object for component [" 322 + name + "]"); 323 } 324 325 ArrayList 327 attributesSet = new ArrayList (), 328 constructorsSet = new ArrayList (), 329 operationsSet = new ArrayList (), 330 notificationsSet = new ArrayList (); 331 332 ClassTree tree = new ClassTree(component.getClass()); 333 334 List classes = tree.getOrderedList(); 335 Iterator classesIterator = classes.iterator(); 336 while (classesIterator.hasNext()) { 337 Class exposedClass = (Class ) classesIterator.next(); 338 339 String configName = 340 METADATA_CONFIG_LOCATION + exposedClass.getName(); 341 342 349 350 if (!Config.getInstance().nodeExists(configName)) { 351 if ((ComponentConfiguration.class.isAssignableFrom(exposedClass)) 357 && (!Proxy.isProxyClass(exposedClass))) { 358 359 this.addConfigurationAttributes(exposedClass, 360 attributesSet); 361 } 362 } else { 363 364 MBeanInfoConfiguration mbic = 365 (MBeanInfoConfiguration) 366 Config.getInstance().fetchConfiguration(configName); 367 if (mbic != null) { 368 369 MBeanInfoConfiguration.MBeanAttributeInfoConfiguration[] 371 attrs = mbic.getAttributes(); 372 373 for (int j = 0; j < attrs.length; j++) { 374 MBeanAttributeInfo attributeInfo = 375 new MBeanAttributeInfo ( 376 attrs[j].getName(), 377 attrs[j].getType(), 378 attrs[j].getDescription(), 379 attrs[j].isReadable(), 380 attrs[j].isWritable(), 381 attrs[j].isIs()); 382 attributesSet.remove(attributeInfo); 384 attributesSet.add(attributeInfo); 385 } 386 387 MBeanInfoConfiguration.MBeanConstructorInfoConfiguration[] 389 constructors = mbic.getConstructors(); 390 391 for (int j = 0; j < constructors.length; j++) { 392 MBeanConstructorInfo constructorInfo = 393 new MBeanConstructorInfo ( 394 constructors[j].getName(), 395 constructors[j].getDescription(), 396 loadParameters(constructors[j].getSignature())); 397 398 constructorsSet.remove(constructorInfo); 400 constructorsSet.add(constructorInfo); 401 } 402 403 MBeanInfoConfiguration.MBeanOperationInfoConfiguration[] 405 operations = mbic.getOperations(); 406 407 for (int j = 0; j < operations.length; j++) { 408 MBeanOperationInfo operationInfo = 409 new MBeanOperationInfo ( 410 operations[j].getName(), 411 operations[j].getDescription(), 412 loadParameters(operations[j].getSignature()), 413 operations[j].getReturnType(), 414 operations[j].getImpact().getImpactConstant()); 415 416 operationsSet.remove(operationInfo); 418 operationsSet.add(operationInfo); 419 } 420 421 MBeanInfoConfiguration.MBeanNotificationInfoConfiguration[] 423 notifications = mbic.getNotifications(); 424 425 for (int j = 0; j < notifications.length; j++) { 426 MBeanInfoConfiguration.MBeanNotificationInfoConfiguration notification 427 = notifications[j]; 428 429 MBeanNotificationInfo notificationInfo = 430 new MBeanNotificationInfo ( 431 notification.getNotifTypes(), 432 notification.getName(), 433 notification.getDescription()); 434 435 notificationsSet.remove(notificationInfo); 437 notificationsSet.add(notificationInfo); 438 } 439 } 440 } 441 } 442 443 444 String description = 447 ((ComponentConfiguration) this.component). 448 getComponentDescription(); 449 if (description == null) { 450 description = "No description given."; 451 } 452 453 454 Collections.sort(attributesSet, new MBeanFeatureInfoComparator()); 455 MBeanAttributeInfo [] attributes = 456 (MBeanAttributeInfo []) 457 attributesSet.toArray( 458 new MBeanAttributeInfo [attributesSet.size()]); 459 460 Collections.sort(constructorsSet, new MBeanFeatureInfoComparator()); 461 MBeanConstructorInfo [] constructors = 462 (MBeanConstructorInfo []) 463 constructorsSet.toArray( 464 new MBeanConstructorInfo [constructorsSet.size()]); 465 466 Collections.sort(operationsSet, new MBeanFeatureInfoComparator()); 467 MBeanOperationInfo [] operations = 468 (MBeanOperationInfo []) 469 operationsSet.toArray( 470 new MBeanOperationInfo [operationsSet.size()]); 471 472 Collections.sort(notificationsSet, new MBeanFeatureInfoComparator()); 473 MBeanNotificationInfo [] notifications = 474 (MBeanNotificationInfo []) 475 notificationsSet.toArray( 476 new MBeanNotificationInfo [notificationsSet.size()]); 477 478 MBeanInfo info = 479 new MBeanInfo ( 480 name, 481 description, 482 attributes, 483 constructors, 484 operations, 485 notifications); 486 487 return info; 488 489 } 490 491 496 public static class MBeanFeatureInfoComparator implements Comparator { 497 508 public int compare(Object o1, Object o2) { 509 510 MBeanFeatureInfo f1 = (MBeanFeatureInfo ) o1; 511 MBeanFeatureInfo f2 = (MBeanFeatureInfo ) o2; 512 513 return f1.getName().compareTo(f2.getName()); 514 } 515 } 516 517 528 private void addConfigurationAttributes( 529 Class configurationClass, List attributesSet) { 530 531 try { 532 BeanInfo info = Introspector.getBeanInfo(configurationClass); 535 536 PropertyDescriptor [] descs = info.getPropertyDescriptors(); 537 538 for (int i = 0; i < descs.length; i++) { 539 PropertyDescriptor desc = descs[i]; 540 541 MBeanAttributeInfo mbeanAttributeInfo = 542 new MBeanAttributeInfo ( 543 desc.getName(), 544 desc.getShortDescription(), 547 desc.getReadMethod(), 548 desc.getWriteMethod()); 549 550 attributesSet.add(mbeanAttributeInfo); 551 } 552 } catch (java.beans.IntrospectionException ie) { 553 log.warn("Unable to add configuration to management metadata for" 554 + " interface [" + configurationClass + "]", 555 ie); 556 } catch (javax.management.IntrospectionException ie) { 557 log.warn("Unable to add configuration to management metadata for" 558 + " interface [" + configurationClass + "]", 559 ie); 560 } 561 562 563 } 564 565 566 575 private MBeanParameterInfo [] loadParameters( 576 MBeanInfoConfiguration.MBeanParameterInfoConfiguration[] config) { 577 578 MBeanParameterInfo [] params = new MBeanParameterInfo [config.length]; 579 for (int j = 0; j < config.length; j++) { 580 params[j] = 581 new MBeanParameterInfo ( 582 config[j].getName(), 583 config[j].getType(), 584 config[j].getDescription()); 585 } 586 return params; 587 } 588 589 597 public Class [] getExposedInterfaces() { 598 return new Class [] { 599 ManagementInterceptor.class, 600 NotificationBroadcaster .class, 601 EventManager.class }; 602 } 603 604 605 606 622 public Object invoke( 623 String actionName, Object [] params, String [] signature) 624 throws MBeanException , ReflectionException { 625 626 627 Class [] paramTypes = new Class [signature.length]; 628 try { 629 for (int i = 0; i < signature.length; i++) { 630 paramTypes[i] = 631 Class.forName( 632 signature[i], 633 true, 634 this.getClass().getClassLoader()); 635 } 636 } catch (ClassNotFoundException cnfe) { 637 throw new ReflectionException (cnfe); 638 } 639 640 Class objectClass = this.component.getClass(); 641 642 try { 643 Method method = objectClass.getMethod(actionName, paramTypes); 644 645 return method.invoke(this.component, params); 646 647 } catch (NoSuchMethodException e) { 648 throw new ReflectionException (e); 649 } catch (IllegalAccessException e) { 650 throw new ReflectionException (e); 651 } catch (InvocationTargetException e) { 652 throw new ReflectionException (e); 653 } 654 655 } 656 657 658 675 public void setAttribute(Attribute attribute) 676 throws AttributeNotFoundException , 677 InvalidAttributeValueException , 678 MBeanException , 679 ReflectionException { 680 681 String name = attribute.getName(); 682 Object value = attribute.getValue(); 683 684 try { 685 BeanUtil.setObjectAttribute(this.component, name, value); 686 } catch (NoSuchMethodException e) { 687 throw new ReflectionException (e); 688 } catch (IllegalAccessException e) { 689 throw new ReflectionException (e); 690 } catch (InvocationTargetException ite) { 691 throw new InvalidAttributeValueException ( 692 "The value for attribute [" + name + "] was [" 693 + value + "] and is not valid: " 694 + ExceptionUtility.printStackTracesToString(ite)); 695 696 } catch (IllegalArgumentException iae) { 697 throw new InvalidAttributeValueException ( 698 "The value for attribute [" + name + "] was [" 699 + value + "] and is not valid: " 700 + ExceptionUtility.printStackTracesToString(iae)); 701 } 702 } 703 704 705 712 public AttributeList setAttributes(AttributeList attributeList) { 713 AttributeList resultList = new AttributeList (); 714 for (int i = 0; i < attributeList.size(); i++) { 715 Attribute attribute = (Attribute ) attributeList.get(i); 716 717 try { 718 setAttribute(attribute); 719 resultList.add(attribute); 720 } catch (AttributeNotFoundException anfe) { 721 if (log.isWarnEnabled()) { 722 log.warn( 723 "Unable to set attribute through JMX.", 724 anfe); 725 } 726 } catch (InvalidAttributeValueException iave) { 727 if (log.isWarnEnabled()) { 728 log.warn( 729 "Unable to set attribute through JMX.", 730 iave); 731 } 732 } catch (MBeanException mbe) { 733 if (log.isWarnEnabled()) { 734 log.warn( 735 "Unable to set attribute through JMX.", 736 mbe); 737 } 738 } catch (ReflectionException re) { 739 if (log.isWarnEnabled()) { 740 log.warn( 741 "Unable to set attribute through JMX.", 742 re); 743 } 744 } 745 } 746 747 return resultList; 748 } 749 750 751 758 public void setComponentReference(Component component) { 759 this.component = component; 760 761 if (this.component instanceof MBeanServerService) { 763 log.trace( 764 "Unable to register component [" 765 + this.component.getComponentName() 766 + "] in MBean Server"); 767 return; 768 } 769 770 if (log.isTraceEnabled()) { 771 log.trace( 772 "Registering [" 773 + this.component.getComponentName() 774 + "] in MBean Server"); 775 } 776 777 MBeanServerService mbeanServer = 778 (MBeanServerService) 779 Lookup.getInstance().fetchComponent("/manage/DefaultMBeanServer"); 780 781 782 if (mbeanServer == null) { 784 log.info( 785 "Unable to register component [" 786 + this.component.getComponentName() + "] in " 787 + "MBean Server as we could not get a reference to the " 788 + "MBeanServerService component."); 789 return; 790 } 791 792 MBeanServer server = null; 793 794 try { 795 server = mbeanServer.getMBeanServer(); 796 } catch (MBeanServerRetreiveException e) { 797 log.info( 802 "Unable to register component [" 803 + this.component.getComponentName() + "] in " 804 + "MBean Server as we could not get a reference to the " 805 + "MBeanServer from the MBeanServerService. Caught " 806 + "Exception: " + e + ExceptionUtility.captureStackTrace(e)); 807 808 return; 809 } 810 811 try { 812 StringBuffer objectNameBuffer = new StringBuffer (100); 813 objectNameBuffer.append(config.getObjectNameDomain()); 814 objectNameBuffer.append(":"); 815 816 objectNameBuffer.append( 817 DefaultManagementInterceptorImpl.PROPERTY_NAME); 818 819 objectNameBuffer.append(this.component.getComponentName()); 820 821 objectNameBuffer.append( 822 DefaultManagementInterceptorImpl.PROPERTY_TYPE); 823 824 objectNameBuffer.append( 825 this.componentFunctionalInterface.getName()); 826 827 if (this.config.getEnvironmentName() != null) { 828 objectNameBuffer.append( 829 DefaultManagementInterceptorImpl.PROPERTY_ENVIRONMENT); 830 831 objectNameBuffer.append(this.config.getEnvironmentName()); 832 } 833 834 if (this.config.getInstanceName() != null) { 835 objectNameBuffer.append( 836 DefaultManagementInterceptorImpl.PROPERTY_INSTANCE); 837 838 objectNameBuffer.append(this.config.getInstanceName()); 839 } 840 841 if (config.isUsingVMID()) { 842 objectNameBuffer.append( 843 DefaultManagementInterceptorImpl.PROPERTY_VMID); 844 845 objectNameBuffer.append( 846 DefaultManagementInterceptorImpl.UNIQUE_ID); 847 } 848 849 this.objectName = new ObjectName (objectNameBuffer.toString()); 850 server.registerMBean(this.component, this.objectName); 851 852 } catch (MalformedObjectNameException mone) { 853 throw new InvalidConfigurationException( 854 this.getClass(), 855 null, null, 856 mone); 857 } catch (InstanceAlreadyExistsException iaee) { 858 throw new InvalidConfigurationException( 859 this.getClass(), 860 null, null, 861 iaee); 862 } catch (MBeanRegistrationException mre) { 863 throw new InvalidConfigurationException( 864 this.getClass(), 865 null, null, 866 mre); 867 } catch (NotCompliantMBeanException ncme) { 868 throw new InvalidConfigurationException( 869 this.getClass(), 870 null, null, 871 ncme); 872 } 873 } 874 875 884 public Object invoke(Invocation invocation) throws Throwable { 885 886 Method method = invocation.getMethod(); 887 String methodName = method.getName(); 888 889 if ((LifecycleInterceptor.class.isAssignableFrom( 891 invocation.getTarget().getClass())) 892 893 && (methodName.equals("destroyComponent")) 894 && (this.objectName != null)) { 895 896 if (log.isInfoEnabled()) { 897 log.info("Unregistering mbean [" 898 + this.objectName.getCanonicalName() + "]"); 899 } 900 try { 901 MBeanServerService mbeanServerService = 902 (MBeanServerService) 903 Lookup.getInstance().fetchComponent( 904 this.mbeanServerServiceName); 905 906 mbeanServerService.getMBeanServer().unregisterMBean( 907 this.objectName); 908 909 } catch (Exception e) { 910 log.debug( 911 "Unable to unregister MBeanServerService component [" 912 + this.objectName.getCanonicalName() + "]"); 913 } 914 } 915 916 return this.nextInterceptor.invoke(invocation); 917 } 918 919 920 921 927 public void sendEvent(ComponentEvent componentEvent) { 928 if (this.shouldSendNotifications) { 929 Notification notification = 930 new Notification ( 931 componentEvent.getName(), 932 componentEvent.getSource(), 933 this.notificationSequence++, 934 componentEvent.getMessage()); 935 936 sendNotification(notification); 937 } 938 } 939 940 } 941 | Popular Tags |