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
011package org.picocontainer.gems.jmx;
012
013import javax.management.MBeanServer;
014
015import org.picocontainer.ComponentAdapter;
016import org.picocontainer.gems.GemsCharacteristics;
017import org.picocontainer.Parameter;
018import org.picocontainer.PicoCompositionException;
019import org.picocontainer.ComponentMonitor;
020import org.picocontainer.LifecycleStrategy;
021import org.picocontainer.behaviors.AbstractBehaviorFactory;
022
023import java.lang.management.ManagementFactory;
024import java.util.Properties;
025
026
027/**
028 * {@link org.picocontainer.ComponentFactory} that instantiates {@link JMXExposed} instances.
029 * @author Jörg Schaible
030 */
031@SuppressWarnings("serial")
032public class JMXExposing extends AbstractBehaviorFactory {
033
034        
035        private final MBeanServer mBeanServer;
036    private final DynamicMBeanProvider[] providers;
037
038    /**
039     * Constructs a JMXExposingComponentFactory that uses the system default MBean Server.
040     * @since PicoContainer-Gems 2.4
041     */
042    public JMXExposing() {
043        this(ManagementFactory.getPlatformMBeanServer());
044    }
045    
046    
047    /**
048     * Construct a JMXExposingComponentFactory.
049     * @param mBeanServer The {@link MBeanServer} used for registering the MBean.
050     * @param providers An array with providers for converting the component instance into a
051     *            {@link javax.management.DynamicMBean}.
052     * @throws NullPointerException Thrown if the {@link MBeanServer} or the array with the {@link DynamicMBeanProvider}
053     *             instances is null.
054     */
055    public JMXExposing(
056            final MBeanServer mBeanServer,
057            final DynamicMBeanProvider[] providers) throws NullPointerException {
058        if (mBeanServer == null || providers == null) {
059            throw new NullPointerException();
060        }
061        this.mBeanServer = mBeanServer;
062        this.providers = providers;
063    }
064
065    /**
066     * Construct a JMXExposingComponentFactory. This instance uses a {@link DynamicMBeanComponentProvider} as
067     * default to register any component instance in the {@link MBeanServer}, that is already a
068     * {@link javax.management.DynamicMBean}.
069     * @param mBeanServer The {@link MBeanServer} used for registering the MBean.
070     * @throws NullPointerException Thrown if the {@link MBeanServer} or the array with the {@link DynamicMBeanProvider}
071     *             instances is null.
072     */
073    public JMXExposing(final MBeanServer mBeanServer)
074            throws NullPointerException {
075        this(mBeanServer, new DynamicMBeanProvider[]{new DynamicMBeanComponentProvider()});
076    }
077    
078
079    /**
080     * Retrieve a {@link ComponentAdapter}. Wrap the instance retrieved by the delegate with an instance of a
081     * {@link JMXExposed}.
082     * @see org.picocontainer.ComponentFactory#createComponentAdapter(ComponentMonitor,LifecycleStrategy,Properties,Object,Class,Parameter...)
083     */
084    @Override
085        public <T> ComponentAdapter<T> createComponentAdapter(
086            final ComponentMonitor componentMonitor, final LifecycleStrategy lifecycleStrategy, final Properties componentProperties, final Object componentKey, final Class<T> componentImplementation, final Parameter... parameters)
087            throws PicoCompositionException {
088        final ComponentAdapter<T> delegateAdapter = super.createComponentAdapter(
089                componentMonitor, lifecycleStrategy,
090                componentProperties, componentKey, componentImplementation, parameters);
091        if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, GemsCharacteristics.NO_JMX)) {
092            return delegateAdapter;            
093        } else {                
094                AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, GemsCharacteristics.JMX);
095            return componentMonitor.newBehavior(new JMXExposed<T>(delegateAdapter, mBeanServer, providers));
096        }
097    }
098
099
100    @Override
101        public <T> ComponentAdapter<T> addComponentAdapter(final ComponentMonitor componentMonitor,
102                                                final LifecycleStrategy lifecycleStrategy,
103                                                final Properties componentProperties,
104                                                final ComponentAdapter<T> adapter) {
105        if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, GemsCharacteristics.NO_JMX)) {
106            return super.addComponentAdapter(componentMonitor,
107                                             lifecycleStrategy,
108                                             componentProperties,
109                                             adapter);
110        } else {
111            return componentMonitor.newBehavior(new JMXExposed<T>(super.addComponentAdapter(componentMonitor,
112                                                                     lifecycleStrategy,
113                                                                     componentProperties,
114                                                                     adapter), mBeanServer, providers));
115        }
116
117    }
118}