001 /***************************************************************************** 002 * Copyright (C) NanoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by Michael Ward * 009 *****************************************************************************/ 010 011 package org.picocontainer.gems.jmx; 012 013 import javax.management.DynamicMBean; 014 import javax.management.InstanceNotFoundException; 015 import javax.management.MBeanException; 016 import javax.management.MBeanInfo; 017 import javax.management.NotCompliantMBeanException; 018 import javax.management.RuntimeOperationsException; 019 import javax.management.StandardMBean; 020 import javax.management.modelmbean.InvalidTargetObjectTypeException; 021 import javax.management.modelmbean.ModelMBean; 022 import javax.management.modelmbean.ModelMBeanInfo; 023 import javax.management.modelmbean.RequiredModelMBean; 024 025 026 /** 027 * A factory for DynamicMBeans, that creates MBean instances using the classes {@link StandardMBean} and 028 * {@link ModelMBean} provided by the JMX specification. The implementation offers special support for StandardMBeans 029 * following the naming convention for their management interface using the class name of the component with an appended 030 * <em>MBean</em>. 031 * @author Michael Ward 032 * @author Jörg Schaible 033 */ 034 public class StandardMBeanFactory implements DynamicMBeanFactory { 035 036 /** 037 * Create a StandardMBean for the component. 038 * @param componentInstance {@inheritDoc} 039 * @param management The management interface. If <code>null</code> the implementation will use the interface 040 * complying with the naming convention for management interfaces. 041 * @param mBeanInfo The {@link MBeanInfo} to use. If <code>null</code> the {@link StandardMBean} will use an 042 * automatically generated one. 043 * @return Returns a {@link StandardMBean}. If the <strong>mBeanInfo</strong> was not null, it is an instance of a 044 * {@link StandardNanoMBean}. 045 * @see org.picocontainer.gems.jmx.DynamicMBeanFactory#create(java.lang.Object, java.lang.Class, 046 * javax.management.MBeanInfo) 047 */ 048 public DynamicMBean create(final Object componentInstance, final Class management, final MBeanInfo mBeanInfo) { 049 try { 050 if (mBeanInfo == null) { 051 final Class managementInterface = getManagementInterface(componentInstance.getClass(), management, null); 052 return new StandardMBean(componentInstance, managementInterface); 053 } else if (mBeanInfo instanceof ModelMBeanInfo) { 054 final ModelMBean mBean = new RequiredModelMBean((ModelMBeanInfo)mBeanInfo); 055 try { 056 mBean.setManagedResource(componentInstance, "ObjectReference"); 057 } catch (final InvalidTargetObjectTypeException e) { 058 // N/A: "ObjectReference" is a valid reference type 059 } catch (final InstanceNotFoundException e) { 060 // N/A: the instance was a valid object 061 } 062 return mBean; 063 } else { 064 final Class<?> managementInterface = getManagementInterface( 065 componentInstance.getClass(), management, mBeanInfo); 066 return new StandardNanoMBean(componentInstance, managementInterface, mBeanInfo); 067 } 068 } catch (final ClassNotFoundException e) { 069 throw new JMXRegistrationException("Cannot load management interface for StandardMBean", e); 070 } catch (final NotCompliantMBeanException e) { 071 throw new JMXRegistrationException("Cannot create StandardMBean", e); 072 } catch (final RuntimeOperationsException e) { 073 throw new JMXRegistrationException("Cannot create ModelMBean", e); 074 } catch (final MBeanException e) { 075 throw new JMXRegistrationException("Cannot create ModelMBean", e); 076 } 077 } 078 079 private Class getManagementInterface(final Class type, final Class management, final MBeanInfo mBeanInfo) 080 throws ClassNotFoundException { 081 final Class managementInterface; 082 if (management == null) { 083 managementInterface = getDefaultManagementInterface(type, mBeanInfo); 084 } else { 085 managementInterface = management; 086 } 087 return managementInterface; 088 } 089 090 /** 091 * Determin the management interface for the given type. The class name of the given type is used as class name of 092 * the mBean unless the caller has provided a {@link MBeanInfo}, the class name of the MBean is retrieved a 093 * MBeanInfo that defines this name. Following the naming conventions is the name of the management interface the 094 * same as the class name of the MBean with an appended <em>MBean</em>. The {@link ClassLoader} of the type is 095 * used to load the interface type. 096 * @param type The class of the MBean. 097 * @param mBeanInfo The {@link MBeanInfo} for the MBean. May be <code>null</code>. 098 * @return Returns the default management interface. 099 * @throws ClassNotFoundException If the management interface cannot be found. 100 */ 101 public Class getDefaultManagementInterface(final Class type, final MBeanInfo mBeanInfo) 102 throws ClassNotFoundException { 103 final ClassLoader classLoader = type.getClassLoader() != null ? type.getClassLoader() : Thread.currentThread() 104 .getContextClassLoader(); 105 return classLoader.loadClass((mBeanInfo == null ? type.getName() : mBeanInfo.getClassName()) + "MBean"); 106 } 107 }