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