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 Joerg Schaible * 009 *****************************************************************************/ 010 011 package org.picocontainer.gems.jmx; 012 013 import org.picocontainer.ComponentAdapter; 014 import org.picocontainer.PicoContainer; 015 016 import javax.management.DynamicMBean; 017 import javax.management.MBeanInfo; 018 import javax.management.MalformedObjectNameException; 019 import javax.management.ObjectName; 020 021 022 /** 023 * A DynamicMBeanProvider that constructs StandardMBean instances that as long as an ObjectName and a MBeanInfo can be 024 * generated for the component. 025 * @author Jörg Schaible 026 */ 027 public abstract class AbstractConstructingProvider implements DynamicMBeanProvider { 028 029 /** 030 * Create a StandardMBean from the component provided by the ComponentAdapter. One of the registered 031 * {@link MBeanInfoProvider} instances must provide a {@link MBeanInfo} for the component and the registered 032 * {@link ObjectNameFactory} has to provide a proper {@link ObjectName}. 033 * <p> 034 * Note: An instance of the component is only created, if a management interface is available. 035 * </p> 036 * @see org.picocontainer.gems.jmx.DynamicMBeanProvider#provide(org.picocontainer.PicoContainer, 037 * org.picocontainer.ComponentAdapter) 038 */ 039 public JMXRegistrationInfo provide(final PicoContainer picoContainer, final ComponentAdapter componentAdapter) { 040 041 // locate MBeanInfo 042 MBeanInfo mBeanInfo = null; 043 MBeanInfoProvider[] mBeanInfoProviders = getMBeanInfoProviders(); 044 for (int i = 0; i < mBeanInfoProviders.length && mBeanInfo == null; ++i) { 045 mBeanInfo = mBeanInfoProviders[i].provide(picoContainer, componentAdapter); 046 } 047 048 Class management = null; 049 try { 050 // throws ClassNotFoundException if not successful 051 management = getManagementInterface(componentAdapter.getComponentImplementation(), mBeanInfo); 052 } catch (final ClassNotFoundException e) { 053 // No management interface available 054 } 055 056 if( management != null || mBeanInfo != null ) { 057 try { 058 // create MBean 059 final DynamicMBean mBean = getMBeanFactory().create( 060 componentAdapter.getComponentInstance(picoContainer,null), management, mBeanInfo); 061 final ObjectName objectName = getObjectNameFactory().create(componentAdapter.getComponentKey(), mBean); 062 if (objectName != null) { 063 return new JMXRegistrationInfo(objectName, mBean); 064 } 065 } catch (final MalformedObjectNameException e) { 066 throw new JMXRegistrationException("Cannot create ObjectName for component '" 067 + componentAdapter.getComponentKey() 068 + "'", e); 069 } 070 } 071 return null; 072 } 073 074 /** 075 * @return Returns the {@link DynamicMBeanFactory} to use. 076 */ 077 protected abstract DynamicMBeanFactory getMBeanFactory(); 078 079 /** 080 * Deliver the ObjectNameFactory used to provide the {@link ObjectName} instances registering the MBeans. 081 * @return Return the {@link ObjectNameFactory} instance. 082 */ 083 protected abstract ObjectNameFactory getObjectNameFactory(); 084 085 /** 086 * Deliver the MBeanInfoProvider instances to use. The instances are used in the delivered sequence to retrieve a 087 * {@link MBeanInfo} for a MBean to create. It is valid for an implementation to return an empty array. 088 * @return Return an array of {@link MBeanInfoProvider} instances. 089 */ 090 protected abstract MBeanInfoProvider[] getMBeanInfoProviders(); 091 092 /** 093 * Determin the management interface from the component implementation type and an optional MBeanInfo instance. 094 * @param implementation The type of the component's implementation. 095 * @param mBeanInfo The {@link MBeanInfo} to expose the component. May be <code>null</code>. 096 * @return Returns the management interface. 097 * @throws ClassNotFoundException Thrown if no interface can be determined. 098 */ 099 protected abstract Class getManagementInterface(final Class implementation, final MBeanInfo mBeanInfo) 100 throws ClassNotFoundException; 101 }