    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&ouml;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    }