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: import org.picocontainer.PicoCompositionException;
014: import org.picocontainer.behaviors.AbstractBehavior;
015: import org.picocontainer.behaviors.Cached;
016:
017: import java.util.List;
018: import java.util.ArrayList;
019: import javax.management.InstanceAlreadyExistsException;
020: import javax.management.MBeanRegistrationException;
021: import javax.management.MBeanServer;
022: import javax.management.NotCompliantMBeanException;
023: import javax.management.ObjectName;
024: import javax.management.InstanceNotFoundException;
025:
026: /**
027: * {@link ComponentAdapter} that is exposing a component as MBean in a MBeanServer.
028: * @author Jörg Schaible
029: */
030: public class JMXExposed extends AbstractBehavior {
031:
032: private final MBeanServer mBeanServer;
033: private final DynamicMBeanProvider[] providers;
034: private List registeredObjectNames;
035:
036: /**
037: * Construct a JMXExposed behaviour
038: * @param delegate The delegated {@link ComponentAdapter}.
039: * @param mBeanServer The {@link MBeanServer} used for registering the MBean.
040: * @param providers An array with providers for converting the component instance into a
041: * {@link javax.management.DynamicMBean}.
042: * @throws NullPointerException Thrown if the {@link MBeanServer} or the array with the {@link DynamicMBeanProvider}
043: * instances is null.
044: */
045: public JMXExposed(final ComponentAdapter delegate,
046: final MBeanServer mBeanServer,
047: final DynamicMBeanProvider[] providers)
048: throws NullPointerException {
049: super (delegate);
050: if (mBeanServer == null || providers == null) {
051: throw new NullPointerException();
052: }
053: this .mBeanServer = mBeanServer;
054: this .providers = providers;
055: }
056:
057: /**
058: * Construct a JMXExposed behaviour. This instance uses a {@link DynamicMBeanComponentProvider} as default to
059: * register any component instance in the {@link MBeanServer}, that is already a
060: * {@link javax.management.DynamicMBean}.
061: * @param delegate The delegated {@link ComponentAdapter}.
062: * @param mBeanServer The {@link MBeanServer} used for registering the MBean.
063: * @throws NullPointerException Thrown if the {@link MBeanServer} or the array with the {@link DynamicMBeanProvider}
064: * instances is null.
065: */
066: public JMXExposed(final ComponentAdapter delegate,
067: final MBeanServer mBeanServer) throws NullPointerException {
068: this (
069: delegate,
070: mBeanServer,
071: new DynamicMBeanProvider[] { new DynamicMBeanComponentProvider() });
072: }
073:
074: /**
075: * Retrieve the component instance. The implementation will automatically register it in the {@link MBeanServer},
076: * if a provider can return a {@link javax.management.DynamicMBean} for it.
077: * <p>
078: * Note, that you will have to wrap this {@link ComponentAdapter} with a {@link Cached} to avoid
079: * the registration of the same component again.
080: * </p>
081: * @throws PicoCompositionException Thrown by the delegate or if the registering of the
082: * {@link javax.management.DynamicMBean} in the {@link MBeanServer } fails.
083: * @see AbstractBehavior#getComponentInstance(org.picocontainer.PicoContainer)
084: */
085: public Object getComponentInstance(final PicoContainer container)
086: throws PicoCompositionException {
087: final ComponentAdapter componentAdapter = new Cached(
088: getDelegate());
089: final Object componentInstance = componentAdapter
090: .getComponentInstance(container);
091: for (DynamicMBeanProvider provider : providers) {
092: final JMXRegistrationInfo info = provider.provide(
093: container, componentAdapter);
094: if (info != null) {
095: Exception exception = null;
096: try {
097: mBeanServer.registerMBean(info.getMBean(), info
098: .getObjectName());
099: } catch (final InstanceAlreadyExistsException e) {
100: exception = e;
101: } catch (final MBeanRegistrationException e) {
102: exception = e;
103: } catch (final NotCompliantMBeanException e) {
104: exception = e;
105: }
106: if (null == registeredObjectNames) {
107: registeredObjectNames = new ArrayList();
108: }
109: registeredObjectNames.add(info.getObjectName());
110: if (exception != null) {
111: throw new PicoCompositionException(
112: "Registering MBean failed", exception);
113: }
114: }
115: }
116: return componentInstance;
117: }
118:
119: public String getDescriptor() {
120: return "ExposedJMX";
121: }
122:
123: public void dispose(Object component) {
124: if (null != registeredObjectNames) {
125: for (Object registeredObjectName : registeredObjectNames) {
126: try {
127: mBeanServer
128: .unregisterMBean((ObjectName) registeredObjectName);
129: } catch (InstanceNotFoundException e) {
130: throw new JMXRegistrationException(e);
131: } catch (MBeanRegistrationException e) {
132: throw new JMXRegistrationException(e);
133: }
134: }
135: }
136:
137: if (super .hasLifecycle(getComponentImplementation())) {
138: super .dispose(component);
139: }
140: }
141:
142: public boolean hasLifecycle(Class type) {
143: return true;
144: }
145:
146: }
|