    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 java.util.HashMap;
    014    import java.util.Map;
    015
    016    import javax.management.DynamicMBean;
    017    import javax.management.MBeanInfo;
    018    import javax.management.ObjectName;
    019
    020    import org.picocontainer.ComponentAdapter;
    021    import org.picocontainer.PicoContainer;
    022
    023
    024    /**
    025     * A DynamicMBeanProvider, that creates DynamicMBeans for registered Pico components on the fly.
    026     * @author Michael Ward
    027     * @author J&ouml;rg Schaible
    028     */
    029    public class RegisteredMBeanConstructingProvider implements DynamicMBeanProvider {
    030
    031        private final DynamicMBeanFactory factory;
    032        private final Map registry;
    033
    034        /**
    035         * Construct a RegisteredMBeanConstructingProvider with a {@link StandardMBeanFactory} as default.
    036         */
    037        public RegisteredMBeanConstructingProvider() {
    038            this(new StandardMBeanFactory());
    039        }
    040
    041        /**
    042         * Construct a RegisteredMBeanConstructingProvider, that uses a specific {@link DynamicMBeanFactory}.
    043         * @param factory
    044         */
    045        public RegisteredMBeanConstructingProvider(final DynamicMBeanFactory factory) {
    046            this.factory = factory;
    047            this.registry = new HashMap();
    048        }
    049
    050        /**
    051         * Provide a DynamicMBean for the given Pico component. The implementation will lookup the component's key in the
    052         * internal registry. Only components that were registered with additional information will be considered and a
    053         * {@link DynamicMBean} will be created for them using the {@link DynamicMBeanFactory}. If the component key is of
    054         * type class, it is used as management interface.
    055         * @see org.picocontainer.gems.jmx.DynamicMBeanProvider#provide(PicoContainer, ComponentAdapter)
    056         */
    057        public JMXRegistrationInfo provide(final PicoContainer picoContainer, final ComponentAdapter componentAdapter) {
    058            final Object key = componentAdapter.getComponentKey();
    059            final MBeanInfoWrapper wrapper = (MBeanInfoWrapper)registry.get(key);
    060            if (wrapper != null) {
    061                final Object instance = componentAdapter.getComponentInstance(picoContainer, ComponentAdapter.NOTHING.class);
    062                final Class management = wrapper.getManagementInterface() != null
    063                                                                                 ? wrapper.getManagementInterface()
    064                                                                                 : key instanceof Class
    065                                                                                                       ? (Class)key
    066                                                                                                       : instance
    067                                                                                                               .getClass();
    068                final DynamicMBean mBean = factory.create(instance, management, wrapper.getMBeanInfo());
    069                return new JMXRegistrationInfo(wrapper.getObjectName(), mBean);
    070            }
    071            return null;
    072        }
    073
    074        /**
    075         * Register a specific Pico component by key with an MBeanInfo and an ObjectName.
    076         * @param componentKey The key of the Pico component.
    077         * @param objectName The {@link ObjectName} of the MBean.
    078         * @param management The management interface.
    079         * @param mBeanInfo The {@link MBeanInfo} of the MBean.
    080         */
    081        public void register(
    082                final Object componentKey, final ObjectName objectName, final Class management, final MBeanInfo mBeanInfo) {
    083            registry.put(componentKey, new MBeanInfoWrapper(mBeanInfo, objectName, management));
    084        }
    085
    086        /**
    087         * Register a specific Pico component by key with an MBeanInfo and an ObjectName.
    088         * @param componentKey The key of the Pico component.
    089         * @param objectName The {@link ObjectName} of the MBean.
    090         * @param mBeanInfo The {@link MBeanInfo} of the MBean.
    091         */
    092        public void register(final Object componentKey, final ObjectName objectName, final MBeanInfo mBeanInfo) {
    093            register(componentKey, objectName, null, mBeanInfo);
    094        }
    095
    096        /**
    097         * Register a specific Pico component with an MBeanInfo and an ObjectName. The implementation class of the
    098         * {@link DynamicMBean} must be the key of the Pico component.
    099         * @param objectName The {@link ObjectName} of the MBean.
    100         * @param mBeanInfo The {@link MBeanInfo} of the MBean.
    101         */
    102        public void register(final ObjectName objectName, final MBeanInfo mBeanInfo) {
    103            try {
    104                register(getClass().getClassLoader().loadClass(mBeanInfo.getClassName()), objectName, mBeanInfo);
    105            } catch (final ClassNotFoundException e) {
    106                throw new JMXRegistrationException("Cannot access class " + mBeanInfo.getClassName() + " of MBean", e);
    107            }
    108        }
    109
    110        /**
    111         * Register a specific Pico component by key with an ObjectName.
    112         * @param componentKey The key of the Pico component.
    113         * @param objectName The {@link ObjectName} of the MBean.
    114         */
    115        public void register(final Object componentKey, final ObjectName objectName) {
    116            registry.put(componentKey, new MBeanInfoWrapper(null, objectName, null));
    117        }
    118
    119        /**
    120         * Simple wrapper to tie a MBeanInfo to an ObjectName
    121         */
    122        private static class MBeanInfoWrapper {
    123            private final MBeanInfo mBeanInfo;
    124            private final ObjectName objectName;
    125            private final Class managementInterface;
    126
    127            MBeanInfoWrapper(final MBeanInfo mBeanInfo, final ObjectName objectName, final Class management) {
    128                this.mBeanInfo = mBeanInfo;
    129                this.objectName = objectName;
    130                this.managementInterface = management;
    131            }
    132
    133            MBeanInfo getMBeanInfo() {
    134                return mBeanInfo;
    135            }
    136
    137            ObjectName getObjectName() {
    138                return objectName;
    139            }
    140
    141            Class getManagementInterface() {
    142                return managementInterface;
    143            }
    144        }
    145
    146    }