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: *****************************************************************************/package org.picocontainer.gems.jmx;
010:
011: import java.util.HashSet;
012: import java.util.Set;
013:
014: import javax.management.DynamicMBean;
015: import javax.management.JMException;
016: import javax.management.MBeanServer;
017: import javax.management.ObjectInstance;
018: import javax.management.ObjectName;
019:
020: import org.picocontainer.ComponentAdapter;
021: import org.picocontainer.PicoContainer;
022: import org.picocontainer.visitors.TraversalCheckingVisitor;
023:
024: /**
025: * A {@link org.picocontainer.PicoVisitor} to register JMX components for components of a {@link PicoContainer} tree in
026: * a {@link MBeanServer}.
027: * @author Michael Ward
028: * @author Jörg Schaible
029: * @version $Revision: 3905 $
030: */
031: public class JMXVisitor extends TraversalCheckingVisitor {
032: private final DynamicMBeanProvider[] mBeanProviders;
033: private final MBeanServer mBeanServer;
034: private final Set visited;
035: private final Set registeredInfo;
036: private PicoContainer picoContainer;
037:
038: /**
039: * Construct a JMXVisitor. This instance will register by default any component in the {@link MBeanServer}, that is
040: * already a {@link DynamicMBean}. The {@link ObjectName} will use the default domain of the MBeanServer and has a
041: * <em>type</em> key with the class name (without package name) as value.
042: * @param server The {@link MBeanServer}to use for registering the MBeans.
043: */
044: public JMXVisitor(final MBeanServer server) {
045: this (
046: server,
047: new DynamicMBeanProvider[] { new DynamicMBeanComponentProvider() });
048: }
049:
050: /**
051: * Construct a JMXVisitor.
052: * @param server The {@link MBeanServer} to use for registering the MBeans.
053: * @param providers The providers to deliver the DynamicMBeans.
054: */
055: public JMXVisitor(final MBeanServer server,
056: final DynamicMBeanProvider[] providers) {
057: if (server == null) {
058: throw new NullPointerException(
059: "MBeanServer may not be null");
060: }
061: if (providers == null) {
062: throw new NullPointerException(
063: "DynamicMBeanProvider[] may not be null");
064: }
065: if (providers.length == 0) {
066: throw new IllegalArgumentException(
067: "DynamicMBeanProvider[] may not be empty");
068: }
069: mBeanServer = server;
070: mBeanProviders = providers;
071: visited = new HashSet();
072: registeredInfo = new HashSet();
073: }
074:
075: /**
076: * Entry point for the visitor traversal.
077: * @return Returns a {@link Set} with all ObjectInstance instances retrieved from the {@link MBeanServer} for the
078: * registered MBeans.
079: * @see org.picocontainer.visitors.AbstractPicoVisitor#traverse(java.lang.Object)
080: */
081: public Object traverse(final Object node) {
082: super .traverse(node);
083: picoContainer = null;
084: final Set set = new HashSet(registeredInfo);
085: registeredInfo.clear();
086: return set;
087: }
088:
089: /**
090: * Provides the PicoContainer, that can resolve the components to register as MBean.
091: * @see org.picocontainer.PicoVisitor#visitContainer(org.picocontainer.PicoContainer)
092: */
093: public void visitContainer(final PicoContainer pico) {
094: super .visitContainer(pico);
095: picoContainer = pico;
096: visited.clear();
097: }
098:
099: /**
100: * Register the component as MBean. The implementation uses the known DynamicMBeanProvider instances to get the
101: * MBean from the component.
102: * @see org.picocontainer.PicoVisitor#visitComponentAdapter(org.picocontainer.ComponentAdapter)
103: */
104: public void visitComponentAdapter(
105: final ComponentAdapter componentAdapter) {
106: super .visitComponentAdapter(componentAdapter);
107: if (picoContainer == null) {
108: throw new JMXRegistrationException(
109: "Cannot start JMXVisitor traversal with a ComponentAdapter");
110: }
111: if (!visited.contains(componentAdapter.getComponentKey())) {
112: visited.add(componentAdapter.getComponentKey());
113: for (final DynamicMBeanProvider provider : mBeanProviders) {
114: final JMXRegistrationInfo info = provider.provide(
115: picoContainer, componentAdapter);
116: if (info != null) {
117: registeredInfo.add(register(info.getMBean(), info
118: .getObjectName()));
119: break;
120: }
121: }
122: }
123: }
124:
125: /**
126: * Register a MBean in the MBeanServer.
127: * @param dynamicMBean the {@link DynamicMBean} to register.
128: * @param objectName the {@link ObjectName} of the MBean registered the {@link MBeanServer}.
129: * @return Returns the {@link ObjectInstance} returned from the MBeanServer after registration.
130: * @throws JMXRegistrationException Thrown if MBean cannot be registered.
131: */
132: protected ObjectInstance register(final DynamicMBean dynamicMBean,
133: final ObjectName objectName)
134: throws JMXRegistrationException {
135: try {
136: return mBeanServer.registerMBean(dynamicMBean, objectName);
137: } catch (final JMException e) {
138: throw new JMXRegistrationException(
139: "Unable to register MBean to MBean Server", e);
140: }
141: }
142: }
|