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ö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 }