Source Code Cross Referenced for MBeanExporter.java in  » J2EE » spring-framework-2.5 » org » springframework » jmx » export » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.jmx.export 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.jmx.export;
0018:
0019:        import java.util.ArrayList;
0020:        import java.util.Arrays;
0021:        import java.util.HashMap;
0022:        import java.util.HashSet;
0023:        import java.util.Iterator;
0024:        import java.util.List;
0025:        import java.util.Map;
0026:        import java.util.Set;
0027:
0028:        import javax.management.DynamicMBean;
0029:        import javax.management.InstanceNotFoundException;
0030:        import javax.management.JMException;
0031:        import javax.management.MBeanException;
0032:        import javax.management.MBeanServer;
0033:        import javax.management.MalformedObjectNameException;
0034:        import javax.management.NotCompliantMBeanException;
0035:        import javax.management.NotificationFilter;
0036:        import javax.management.NotificationListener;
0037:        import javax.management.ObjectName;
0038:        import javax.management.StandardMBean;
0039:        import javax.management.modelmbean.ModelMBean;
0040:        import javax.management.modelmbean.ModelMBeanInfo;
0041:        import javax.management.modelmbean.RequiredModelMBean;
0042:
0043:        import org.springframework.aop.framework.ProxyFactory;
0044:        import org.springframework.aop.support.AopUtils;
0045:        import org.springframework.aop.target.LazyInitTargetSource;
0046:        import org.springframework.beans.factory.BeanClassLoaderAware;
0047:        import org.springframework.beans.factory.BeanFactory;
0048:        import org.springframework.beans.factory.BeanFactoryAware;
0049:        import org.springframework.beans.factory.DisposableBean;
0050:        import org.springframework.beans.factory.InitializingBean;
0051:        import org.springframework.beans.factory.ListableBeanFactory;
0052:        import org.springframework.beans.factory.NoSuchBeanDefinitionException;
0053:        import org.springframework.beans.factory.config.BeanDefinition;
0054:        import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
0055:        import org.springframework.core.Constants;
0056:        import org.springframework.jmx.export.assembler.AutodetectCapableMBeanInfoAssembler;
0057:        import org.springframework.jmx.export.assembler.MBeanInfoAssembler;
0058:        import org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler;
0059:        import org.springframework.jmx.export.naming.KeyNamingStrategy;
0060:        import org.springframework.jmx.export.naming.ObjectNamingStrategy;
0061:        import org.springframework.jmx.export.naming.SelfNaming;
0062:        import org.springframework.jmx.export.notification.ModelMBeanNotificationPublisher;
0063:        import org.springframework.jmx.export.notification.NotificationPublisherAware;
0064:        import org.springframework.jmx.support.JmxUtils;
0065:        import org.springframework.jmx.support.MBeanRegistrationSupport;
0066:        import org.springframework.jmx.support.ObjectNameManager;
0067:        import org.springframework.util.Assert;
0068:        import org.springframework.util.ClassUtils;
0069:        import org.springframework.util.CollectionUtils;
0070:        import org.springframework.util.ObjectUtils;
0071:
0072:        /**
0073:         * JMX exporter that allows for exposing any <i>Spring-managed bean</i>
0074:         * to a JMX <code>MBeanServer</code>, without the need to define any
0075:         * JMX-specific information in the bean classes.
0076:         *
0077:         * <p>If the bean implements one of the JMX management interfaces,
0078:         * then MBeanExporter can simply register the MBean with the server
0079:         * automatically, through its autodetection process.
0080:         *
0081:         * <p>If the bean does not implement one of the JMX management interfaces,
0082:         * then MBeanExporter will create the management information using the
0083:         * supplied {@link MBeanInfoAssembler} implementation.
0084:         *
0085:         * <p>A list of {@link MBeanExporterListener MBeanExporterListeners}
0086:         * can be registered via the
0087:         * {@link #setListeners(MBeanExporterListener[]) listeners} property,
0088:         * allowing application code to be notified of MBean registration and
0089:         * unregistration events.
0090:         *
0091:         * @author Rob Harrop
0092:         * @author Juergen Hoeller
0093:         * @author Rick Evans
0094:         * @author Mark Fisher
0095:         * @since 1.2
0096:         * @see #setBeans
0097:         * @see #setAutodetect
0098:         * @see #setAssembler
0099:         * @see #setListeners
0100:         * @see org.springframework.jmx.export.assembler.MBeanInfoAssembler
0101:         * @see MBeanExporterListener
0102:         */
0103:        public class MBeanExporter extends MBeanRegistrationSupport implements 
0104:                MBeanExportOperations, BeanClassLoaderAware, BeanFactoryAware,
0105:                InitializingBean, DisposableBean {
0106:
0107:            /**
0108:             * Autodetection mode indicating that no autodetection should be used.
0109:             */
0110:            public static final int AUTODETECT_NONE = 0;
0111:
0112:            /**
0113:             * Autodetection mode indicating that only valid MBeans should be autodetected.
0114:             */
0115:            public static final int AUTODETECT_MBEAN = 1;
0116:
0117:            /**
0118:             * Autodetection mode indicating that only the {@link MBeanInfoAssembler} should be able
0119:             * to autodetect beans.
0120:             */
0121:            public static final int AUTODETECT_ASSEMBLER = 2;
0122:
0123:            /**
0124:             * Autodetection mode indicating that all autodetection mechanisms should be used.
0125:             */
0126:            public static final int AUTODETECT_ALL = AUTODETECT_MBEAN
0127:                    | AUTODETECT_ASSEMBLER;
0128:
0129:            /**
0130:             * Wildcard used to map a {@link javax.management.NotificationListener}
0131:             * to all MBeans registered by the <code>MBeanExporter</code>.
0132:             */
0133:            private static final String WILDCARD = "*";
0134:
0135:            /** Constant for the JMX <code>mr_type</code> "ObjectReference" */
0136:            private static final String MR_TYPE_OBJECT_REFERENCE = "ObjectReference";
0137:
0138:            /** Prefix for the autodetect constants defined in this class */
0139:            private static final String CONSTANT_PREFIX_AUTODETECT = "AUTODETECT_";
0140:
0141:            /** Constants instance for this class */
0142:            private static final Constants constants = new Constants(
0143:                    MBeanExporter.class);
0144:
0145:            /** The beans to be exposed as JMX managed resources, with JMX names as keys */
0146:            private Map beans;
0147:
0148:            /** The autodetect mode to use for this MBeanExporter */
0149:            private Integer autodetectMode;
0150:
0151:            /** Indicates whether Spring should modify generated ObjectNames */
0152:            private boolean ensureUniqueRuntimeObjectNames = true;
0153:
0154:            /** Indicates whether Spring should expose the managed resource ClassLoader in the MBean */
0155:            private boolean exposeManagedResourceClassLoader = false;
0156:
0157:            /** A set of bean names that should be excluded from autodetection */
0158:            private Set excludedBeans;
0159:
0160:            /** The MBeanExporterListeners registered with this exporter. */
0161:            private MBeanExporterListener[] listeners;
0162:
0163:            /** The NotificationListeners to register for the MBeans registered by this exporter */
0164:            private NotificationListenerBean[] notificationListeners = new NotificationListenerBean[0];
0165:
0166:            /** Stores the MBeanInfoAssembler to use for this exporter */
0167:            private MBeanInfoAssembler assembler = new SimpleReflectiveMBeanInfoAssembler();
0168:
0169:            /** The strategy to use for creating ObjectNames for an object */
0170:            private ObjectNamingStrategy namingStrategy = new KeyNamingStrategy();
0171:
0172:            /** Stores the ClassLoader to use for generating lazy-init proxies */
0173:            private ClassLoader beanClassLoader = ClassUtils
0174:                    .getDefaultClassLoader();
0175:
0176:            /** Stores the BeanFactory for use in autodetection process */
0177:            private ListableBeanFactory beanFactory;
0178:
0179:            /**
0180:             * Supply a <code>Map</code> of beans to be registered with the JMX
0181:             * <code>MBeanServer</code>.
0182:             * <p>The String keys are the basis for the creation of JMX object names.
0183:             * By default, a JMX <code>ObjectName</code> will be created straight
0184:             * from the given key. This can be customized through specifying a
0185:             * custom <code>NamingStrategy</code>.
0186:             * <p>Both bean instances and bean names are allowed as values.
0187:             * Bean instances are typically linked in through bean references.
0188:             * Bean names will be resolved as beans in the current factory, respecting
0189:             * lazy-init markers (that is, not triggering initialization of such beans).
0190:             * @param beans Map with JMX names as keys and bean instances or bean names
0191:             * as values
0192:             * @see #setNamingStrategy
0193:             * @see org.springframework.jmx.export.naming.KeyNamingStrategy
0194:             * @see javax.management.ObjectName#ObjectName(String)
0195:             */
0196:            public void setBeans(Map beans) {
0197:                this .beans = beans;
0198:            }
0199:
0200:            /**
0201:             * Set whether to autodetect MBeans in the bean factory that this exporter
0202:             * runs in. Will also ask an <code>AutodetectCapableMBeanInfoAssembler</code>
0203:             * if available.
0204:             * <p>This feature is turned off by default. Explicitly specify
0205:             * <code>true</code> here to enable autodetection.
0206:             * @see #setAssembler
0207:             * @see AutodetectCapableMBeanInfoAssembler
0208:             * @see #isMBean
0209:             */
0210:            public void setAutodetect(boolean autodetect) {
0211:                this .autodetectMode = new Integer(autodetect ? AUTODETECT_ALL
0212:                        : AUTODETECT_NONE);
0213:            }
0214:
0215:            /**
0216:             * Sets the autodetection mode to use.
0217:             * @exception IllegalArgumentException if the supplied value is not
0218:             * one of the <code>AUTODETECT_</code> constants
0219:             * @see #setAutodetectModeName(String)
0220:             * @see #AUTODETECT_ALL
0221:             * @see #AUTODETECT_ASSEMBLER
0222:             * @see #AUTODETECT_MBEAN
0223:             * @see #AUTODETECT_NONE
0224:             */
0225:            public void setAutodetectMode(int autodetectMode) {
0226:                if (!constants.getValues(CONSTANT_PREFIX_AUTODETECT).contains(
0227:                        new Integer(autodetectMode))) {
0228:                    throw new IllegalArgumentException(
0229:                            "Only values of autodetect constants allowed");
0230:                }
0231:                this .autodetectMode = new Integer(autodetectMode);
0232:            }
0233:
0234:            /**
0235:             * Sets the autodetection mode to use by name.
0236:             * @exception IllegalArgumentException if the supplied value is not resolvable
0237:             * to one of the <code>AUTODETECT_</code> constants or is <code>null</code>
0238:             * @see #setAutodetectMode(int)
0239:             * @see #AUTODETECT_ALL
0240:             * @see #AUTODETECT_ASSEMBLER
0241:             * @see #AUTODETECT_MBEAN
0242:             * @see #AUTODETECT_NONE
0243:             */
0244:            public void setAutodetectModeName(String constantName) {
0245:                if (constantName == null
0246:                        || !constantName.startsWith(CONSTANT_PREFIX_AUTODETECT)) {
0247:                    throw new IllegalArgumentException(
0248:                            "Only autodetect constants allowed");
0249:                }
0250:                this .autodetectMode = (Integer) constants
0251:                        .asNumber(constantName);
0252:            }
0253:
0254:            /**
0255:             * Set the implementation of the <code>MBeanInfoAssembler</code> interface to use
0256:             * for this exporter. Default is a <code>SimpleReflectiveMBeanInfoAssembler</code>.
0257:             * <p>The passed-in assembler can optionally implement the
0258:             * <code>AutodetectCapableMBeanInfoAssembler</code> interface, which enables it
0259:             * to participate in the exporter's MBean autodetection process.
0260:             * @see org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler
0261:             * @see org.springframework.jmx.export.assembler.AutodetectCapableMBeanInfoAssembler
0262:             * @see org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler
0263:             * @see #setAutodetect
0264:             */
0265:            public void setAssembler(MBeanInfoAssembler assembler) {
0266:                this .assembler = assembler;
0267:            }
0268:
0269:            /**
0270:             * Set the implementation of the <code>ObjectNamingStrategy</code> interface
0271:             * to use for this exporter. Default is a <code>KeyNamingStrategy</code>.
0272:             * @see org.springframework.jmx.export.naming.KeyNamingStrategy
0273:             * @see org.springframework.jmx.export.naming.MetadataNamingStrategy
0274:             */
0275:            public void setNamingStrategy(ObjectNamingStrategy namingStrategy) {
0276:                this .namingStrategy = namingStrategy;
0277:            }
0278:
0279:            /**
0280:             * Set the <code>MBeanExporterListener</code>s that should be notified
0281:             * of MBean registration and unregistration events.
0282:             * @see MBeanExporterListener
0283:             */
0284:            public void setListeners(MBeanExporterListener[] listeners) {
0285:                this .listeners = listeners;
0286:            }
0287:
0288:            /**
0289:             * Set the list of names for beans that should be excluded from autodetection.
0290:             */
0291:            public void setExcludedBeans(String[] excludedBeans) {
0292:                this .excludedBeans = (excludedBeans != null ? new HashSet(
0293:                        Arrays.asList(excludedBeans)) : null);
0294:            }
0295:
0296:            /**
0297:             * Indicates whether Spring should ensure that {@link ObjectName ObjectNames}
0298:             * generated by the configured {@link ObjectNamingStrategy} for
0299:             * runtime-registered MBeans should be modified to ensure uniqueness
0300:             * for every instance of a managed <code>Class</code>.
0301:             * <p>The default value is <code>true</code>.
0302:             * @see JmxUtils#appendIdentityToObjectName(javax.management.ObjectName, Object)
0303:             */
0304:            public void setEnsureUniqueRuntimeObjectNames(
0305:                    boolean ensureUniqueRuntimeObjectNames) {
0306:                this .ensureUniqueRuntimeObjectNames = ensureUniqueRuntimeObjectNames;
0307:            }
0308:
0309:            /**
0310:             * Indicates whether or not the managed resource should be exposed on the
0311:             * {@link Thread#getContextClassLoader() thread context ClassLoader} before
0312:             * allowing any invocations on the MBean to occur.
0313:             * <ü>The default value is <code>true</code>, exposing a {@link SpringModelMBean}
0314:             * which performs thread context ClassLoader management. Switch this flag off to
0315:             * expose a standard JMX {@link javax.management.modelmbean.RequiredModelMBean}.
0316:             */
0317:            public void setExposeManagedResourceClassLoader(
0318:                    boolean exposeManagedResourceClassLoader) {
0319:                this .exposeManagedResourceClassLoader = exposeManagedResourceClassLoader;
0320:            }
0321:
0322:            /**
0323:             * Set the {@link NotificationListenerBean NotificationListenerBeans}
0324:             * containing the
0325:             * {@link javax.management.NotificationListener NotificationListeners}
0326:             * that will be registered with the {@link MBeanServer}.
0327:             * @see #setNotificationListenerMappings(java.util.Map)
0328:             * @see NotificationListenerBean
0329:             */
0330:            public void setNotificationListeners(
0331:                    NotificationListenerBean[] notificationListeners) {
0332:                this .notificationListeners = notificationListeners;
0333:            }
0334:
0335:            /**
0336:             * Set the {@link NotificationListener NotificationListeners} to register
0337:             * with the {@link javax.management.MBeanServer}.
0338:             * <P>The key of each entry in the <code>Map</code> is a {@link String}
0339:             * representation of the {@link javax.management.ObjectName} or the bean
0340:             * name of the MBean the listener should be registered for. Specifying an
0341:             * asterisk (<code>*</code>) for a key will cause the listener to be
0342:             * associated with all MBeans registered by this class at startup time.
0343:             * <p>The value of each entry is the
0344:             * {@link javax.management.NotificationListener} to register. For more
0345:             * advanced options such as registering
0346:             * {@link javax.management.NotificationFilter NotificationFilters} and
0347:             * handback objects see {@link #setNotificationListeners(NotificationListenerBean[])}.
0348:             * @throws IllegalArgumentException if the supplied <code>listeners</code> {@link Map} is <code>null</code>.
0349:             */
0350:            public void setNotificationListenerMappings(Map listeners) {
0351:                Assert.notNull(listeners, "'listeners' must not be null");
0352:                List notificationListeners = new ArrayList(listeners.size());
0353:
0354:                for (Iterator iterator = listeners.entrySet().iterator(); iterator
0355:                        .hasNext();) {
0356:                    Map.Entry entry = (Map.Entry) iterator.next();
0357:
0358:                    // Get the listener from the map value.
0359:                    Object value = entry.getValue();
0360:                    if (!(value instanceof  NotificationListener)) {
0361:                        throw new IllegalArgumentException("Map entry value ["
0362:                                + value + "] is not a NotificationListener");
0363:                    }
0364:                    NotificationListenerBean bean = new NotificationListenerBean(
0365:                            (NotificationListener) value);
0366:
0367:                    // Get the ObjectName from the map key.
0368:                    Object key = entry.getKey();
0369:                    if (key != null && !WILDCARD.equals(key)) {
0370:                        // This listener is mapped to a specific ObjectName.
0371:                        bean.setMappedObjectName(entry.getKey().toString());
0372:                    }
0373:
0374:                    notificationListeners.add(bean);
0375:                }
0376:
0377:                this .notificationListeners = (NotificationListenerBean[]) notificationListeners
0378:                        .toArray(new NotificationListenerBean[notificationListeners
0379:                                .size()]);
0380:            }
0381:
0382:            public void setBeanClassLoader(ClassLoader classLoader) {
0383:                this .beanClassLoader = classLoader;
0384:            }
0385:
0386:            /**
0387:             * This callback is only required for resolution of bean names in the
0388:             * {@link #setBeans(java.util.Map) "beans"} {@link Map} and for
0389:             * autodetection of MBeans (in the latter case, a
0390:             * <code>ListableBeanFactory</code> is required).
0391:             * @see #setBeans
0392:             * @see #setAutodetect
0393:             * @throws IllegalArgumentException if the supplied <code>beanFactory</code> is not a {@link ListableBeanFactory}.
0394:             */
0395:            public void setBeanFactory(BeanFactory beanFactory) {
0396:                if (beanFactory instanceof  ListableBeanFactory) {
0397:                    this .beanFactory = (ListableBeanFactory) beanFactory;
0398:                } else {
0399:                    logger
0400:                            .info("MBeanExporter not running in a ListableBeanFactory: Autodetection of MBeans not available.");
0401:                }
0402:            }
0403:
0404:            //---------------------------------------------------------------------
0405:            // Lifecycle in bean factory: automatically register/unregister beans
0406:            //---------------------------------------------------------------------
0407:
0408:            /**
0409:             * Start bean registration automatically when deployed in an
0410:             * <code>ApplicationContext</code>.
0411:             * @see #registerBeans()
0412:             */
0413:            public void afterPropertiesSet() {
0414:                logger.info("Registering beans for JMX exposure on startup");
0415:                registerBeans();
0416:            }
0417:
0418:            /**
0419:             * Unregisters all beans that this exported has exposed via JMX
0420:             * when the enclosing <code>ApplicationContext</code> is destroyed.
0421:             */
0422:            public void destroy() {
0423:                logger.info("Unregistering JMX-exposed beans on shutdown");
0424:                unregisterBeans();
0425:            }
0426:
0427:            //---------------------------------------------------------------------
0428:            // Implementation of MBeanExportOperations interface
0429:            //---------------------------------------------------------------------
0430:
0431:            public ObjectName registerManagedResource(Object managedResource)
0432:                    throws MBeanExportException {
0433:                Assert.notNull(managedResource,
0434:                        "Managed resource must not be null");
0435:                ObjectName objectName = null;
0436:                try {
0437:                    objectName = getObjectName(managedResource, null);
0438:                    if (this .ensureUniqueRuntimeObjectNames) {
0439:                        objectName = JmxUtils.appendIdentityToObjectName(
0440:                                objectName, managedResource);
0441:                    }
0442:                } catch (Exception ex) {
0443:                    throw new MBeanExportException(
0444:                            "Unable to generate ObjectName for MBean ["
0445:                                    + managedResource + "]", ex);
0446:                }
0447:                registerManagedResource(managedResource, objectName);
0448:                return objectName;
0449:            }
0450:
0451:            public void registerManagedResource(Object managedResource,
0452:                    ObjectName objectName) throws MBeanExportException {
0453:                Assert.notNull(managedResource,
0454:                        "Managed resource must not be null");
0455:                Assert.notNull(objectName, "ObjectName must not be null");
0456:                try {
0457:                    if (isMBean(managedResource.getClass())) {
0458:                        doRegister(managedResource, objectName);
0459:                    } else {
0460:                        ModelMBean mbean = createAndConfigureMBean(
0461:                                managedResource, managedResource.getClass()
0462:                                        .getName());
0463:                        doRegister(mbean, objectName);
0464:                        injectNotificationPublisherIfNecessary(managedResource,
0465:                                mbean, objectName);
0466:                    }
0467:                } catch (JMException ex) {
0468:                    throw new UnableToRegisterMBeanException(
0469:                            "Unable to register MBean [" + managedResource
0470:                                    + "] with object name [" + objectName + "]",
0471:                            ex);
0472:                }
0473:            }
0474:
0475:            //---------------------------------------------------------------------
0476:            // Exporter implementation
0477:            //---------------------------------------------------------------------
0478:
0479:            /**
0480:             * Registers the defined beans with the {@link MBeanServer}.
0481:             * <p>Each bean is exposed to the <code>MBeanServer</code> via a
0482:             * <code>ModelMBean</code>. The actual implemetation of the
0483:             * <code>ModelMBean</code> interface used depends on the implementation of
0484:             * the <code>ModelMBeanProvider</code> interface that is configured. By
0485:             * default the <code>RequiredModelMBean</code> class that is supplied with
0486:             * all JMX implementations is used.
0487:             * <p>The management interface produced for each bean is dependent on the
0488:             * <code>MBeanInfoAssembler</code> implementation being used. The
0489:             * <code>ObjectName</code> given to each bean is dependent on the
0490:             * implementation of the <code>ObjectNamingStrategy</code> interface being used.
0491:             */
0492:            protected void registerBeans() {
0493:                // The beans property may be null, for example if we are relying solely on autodetection.
0494:                if (this .beans == null) {
0495:                    this .beans = new HashMap();
0496:                    // Use AUTODETECT_ALL as default in no beans specified explicitly.
0497:                    if (this .autodetectMode == null) {
0498:                        this .autodetectMode = new Integer(AUTODETECT_ALL);
0499:                    }
0500:                }
0501:
0502:                // Perform autodetection, if desired.
0503:                int mode = (this .autodetectMode != null ? this .autodetectMode
0504:                        .intValue() : AUTODETECT_NONE);
0505:                if (mode != AUTODETECT_NONE) {
0506:                    if (this .beanFactory == null) {
0507:                        throw new MBeanExportException(
0508:                                "Cannot autodetect MBeans if not running in a BeanFactory");
0509:                    }
0510:                    if (mode == AUTODETECT_MBEAN || mode == AUTODETECT_ALL) {
0511:                        // Autodetect any beans that are already MBeans.
0512:                        this .logger
0513:                                .debug("Autodetecting user-defined JMX MBeans");
0514:                        autodetectMBeans();
0515:                    }
0516:                    // Allow the assembler a chance to vote for bean inclusion.
0517:                    if ((mode == AUTODETECT_ASSEMBLER || mode == AUTODETECT_ALL)
0518:                            && this .assembler instanceof  AutodetectCapableMBeanInfoAssembler) {
0519:                        autodetectBeans((AutodetectCapableMBeanInfoAssembler) this .assembler);
0520:                    }
0521:                }
0522:
0523:                if (!this .beans.isEmpty()) {
0524:                    // If no server was provided then try to find one. This is useful in an environment
0525:                    // such as JDK 1.5, Tomcat or JBoss where there is already an MBeanServer loaded.
0526:                    if (this .server == null) {
0527:                        this .server = JmxUtils.locateMBeanServer();
0528:                    }
0529:                    try {
0530:                        for (Iterator it = this .beans.entrySet().iterator(); it
0531:                                .hasNext();) {
0532:                            Map.Entry entry = (Map.Entry) it.next();
0533:                            String beanKey = (String) entry.getKey();
0534:                            Object value = entry.getValue();
0535:                            registerBeanNameOrInstance(value, beanKey);
0536:                        }
0537:
0538:                        // All MBeans are now registered successfully - go ahead and register the notification listeners.
0539:                        registerNotificationListeners();
0540:                    } catch (RuntimeException ex) {
0541:                        // Unregister beans already registered by this exporter.
0542:                        unregisterBeans();
0543:                        throw ex;
0544:                    }
0545:                }
0546:            }
0547:
0548:            /**
0549:             * Return whether the specified bean definition should be considered as lazy-init.
0550:             * @param beanFactory the bean factory that is supposed to contain the bean definition
0551:             * @param beanName the name of the bean to check
0552:             * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
0553:             * @see org.springframework.beans.factory.config.BeanDefinition#isLazyInit
0554:             */
0555:            protected boolean isBeanDefinitionLazyInit(
0556:                    ListableBeanFactory beanFactory, String beanName) {
0557:                if (!(beanFactory instanceof  ConfigurableListableBeanFactory)) {
0558:                    return false;
0559:                }
0560:                try {
0561:                    BeanDefinition bd = ((ConfigurableListableBeanFactory) beanFactory)
0562:                            .getBeanDefinition(beanName);
0563:                    return bd.isLazyInit();
0564:                } catch (NoSuchBeanDefinitionException ex) {
0565:                    // Probably a directly registered singleton.
0566:                    return false;
0567:                }
0568:            }
0569:
0570:            /**
0571:             * Registers an individual bean with the {@link #setServer MBeanServer}.
0572:             * <p>This method is responsible for deciding <strong>how</strong> a bean
0573:             * should be exposed to the <code>MBeanServer</code>. Specifically, if the
0574:             * supplied <code>mapValue</code> is the name of a bean that is configured
0575:             * for lazy initialization, then a proxy to the resource is registered with
0576:             * the <code>MBeanServer</code> so that the the lazy load behavior is
0577:             * honored. If the bean is already an MBean then it will be registered
0578:             * directly with the <code>MBeanServer</code> without any intervention. For
0579:             * all other beans or bean names, the resource itself is registered with
0580:             * the <code>MBeanServer</code> directly.
0581:             * @param mapValue the value configured for this bean in the beans map;
0582:             * may be either the <code>String</code> name of a bean, or the bean itself
0583:             * @param beanKey the key associated with this bean in the beans map
0584:             * @return the <code>ObjectName</code> under which the resource was registered
0585:             * @throws MBeanExportException if the export failed
0586:             * @see #setBeans
0587:             * @see #registerBeanInstance
0588:             * @see #registerLazyInit
0589:             */
0590:            protected ObjectName registerBeanNameOrInstance(Object mapValue,
0591:                    String beanKey) throws MBeanExportException {
0592:                try {
0593:                    if (mapValue instanceof  String) {
0594:                        // Bean name pointing to a potentially lazy-init bean in the factory.
0595:                        if (this .beanFactory == null) {
0596:                            throw new MBeanExportException(
0597:                                    "Cannot resolve bean names if not running in a BeanFactory");
0598:                        }
0599:                        String beanName = (String) mapValue;
0600:                        if (isBeanDefinitionLazyInit(this .beanFactory, beanName)) {
0601:                            ObjectName objectName = registerLazyInit(beanName,
0602:                                    beanKey);
0603:                            replaceNotificationListenerBeanNameMappingKeysIfNecessary(
0604:                                    beanName, objectName);
0605:                            return objectName;
0606:                        } else {
0607:                            Object bean = this .beanFactory.getBean(beanName);
0608:                            ObjectName objectName = registerBeanInstance(bean,
0609:                                    beanKey);
0610:                            replaceNotificationListenerBeanNameMappingKeysIfNecessary(
0611:                                    beanName, objectName);
0612:                            return objectName;
0613:                        }
0614:                    } else {
0615:                        // Plain bean instance -> register it directly.
0616:                        if (this .beanFactory != null) {
0617:                            Map beansOfSameType = this .beanFactory
0618:                                    .getBeansOfType(mapValue.getClass(), false,
0619:                                            false);
0620:                            for (Iterator iterator = beansOfSameType.entrySet()
0621:                                    .iterator(); iterator.hasNext();) {
0622:                                Map.Entry entry = (Map.Entry) iterator.next();
0623:                                if (entry.getValue() == mapValue) {
0624:                                    String beanName = (String) entry.getKey();
0625:                                    ObjectName objectName = registerBeanInstance(
0626:                                            mapValue, beanKey);
0627:                                    replaceNotificationListenerBeanNameMappingKeysIfNecessary(
0628:                                            beanName, objectName);
0629:                                    return objectName;
0630:                                }
0631:                            }
0632:                        }
0633:                        return registerBeanInstance(mapValue, beanKey);
0634:                    }
0635:                } catch (Exception ex) {
0636:                    throw new UnableToRegisterMBeanException(
0637:                            "Unable to register MBean [" + mapValue
0638:                                    + "] with key '" + beanKey + "'", ex);
0639:                }
0640:            }
0641:
0642:            /**
0643:             * Replaces any bean names used as keys in the <code>NotificationListener</code>
0644:             * mappings with their corresponding <code>ObjectName</code> values.
0645:             * @param beanName the name of the bean to be registered
0646:             * @param objectName the <code>ObjectName</code> under which the bean will be registered
0647:             * with the <code>MBeanServer</code>
0648:             */
0649:            private void replaceNotificationListenerBeanNameMappingKeysIfNecessary(
0650:                    String beanName, ObjectName objectName) {
0651:                Set mappedListeners = new HashSet();
0652:                String objectNameString = objectName.getCanonicalName();
0653:                for (int i = 0; i < notificationListeners.length; i++) {
0654:                    NotificationListenerBean bean = notificationListeners[i];
0655:                    NotificationListener listener = bean
0656:                            .getNotificationListener();
0657:                    Set newMappedNames = new HashSet();
0658:                    String[] mappedNames = bean.getMappedObjectNames();
0659:                    for (int j = 0; j < mappedNames.length; j++) {
0660:                        String mappedName = mappedNames[j];
0661:                        if (mappedName.equals(beanName)) {
0662:                            mappedName = objectNameString;
0663:                        }
0664:                        if (mappedName.equals(objectNameString)) {
0665:                            // avoid duplicate mappings on beanName and objectName
0666:                            if (!mappedListeners.contains(listener)) {
0667:                                newMappedNames.add(mappedName);
0668:                                mappedListeners.add(listener);
0669:                            }
0670:                        } else {
0671:                            newMappedNames.add(mappedName);
0672:                        }
0673:                    }
0674:                    bean.setMappedObjectNames((String[]) newMappedNames
0675:                            .toArray(new String[newMappedNames.size()]));
0676:                }
0677:            }
0678:
0679:            /**
0680:             * Registers an existing MBean or an MBean adapter for a plain bean
0681:             * with the <code>MBeanServer</code>.
0682:             * @param bean the bean to register, either an MBean or a plain bean
0683:             * @param beanKey the key associated with this bean in the beans map
0684:             * @return the <code>ObjectName</code> under which the bean was registered
0685:             * with the <code>MBeanServer</code>
0686:             */
0687:            private ObjectName registerBeanInstance(Object bean, String beanKey)
0688:                    throws JMException {
0689:                ObjectName objectName = getObjectName(bean, beanKey);
0690:                Object mbeanToExpose = null;
0691:                if (isMBean(bean.getClass())) {
0692:                    mbeanToExpose = bean;
0693:                } else {
0694:                    DynamicMBean adaptedBean = adaptMBeanIfPossible(bean);
0695:                    if (adaptedBean != null) {
0696:                        mbeanToExpose = adaptedBean;
0697:                    }
0698:                }
0699:                if (mbeanToExpose != null) {
0700:                    if (logger.isInfoEnabled()) {
0701:                        logger.info("Located MBean '" + beanKey
0702:                                + "': registering with JMX server as MBean ["
0703:                                + objectName + "]");
0704:                    }
0705:                    doRegister(mbeanToExpose, objectName);
0706:                } else {
0707:                    if (logger.isInfoEnabled()) {
0708:                        logger.info("Located managed bean '" + beanKey
0709:                                + "': registering with JMX server as MBean ["
0710:                                + objectName + "]");
0711:                    }
0712:                    ModelMBean mbean = createAndConfigureMBean(bean, beanKey);
0713:                    doRegister(mbean, objectName);
0714:                    injectNotificationPublisherIfNecessary(bean, mbean,
0715:                            objectName);
0716:                }
0717:                return objectName;
0718:            }
0719:
0720:            /**
0721:             * Registers beans that are configured for lazy initialization with the
0722:             * <code>MBeanServer<code> indirectly through a proxy.
0723:             * @param beanName the name of the bean in the <code>BeanFactory</code>
0724:             * @param beanKey the key associated with this bean in the beans map
0725:             * @return the <code>ObjectName</code> under which the bean was registered
0726:             * with the <code>MBeanServer</code>
0727:             */
0728:            private ObjectName registerLazyInit(String beanName, String beanKey)
0729:                    throws JMException {
0730:                ProxyFactory proxyFactory = new ProxyFactory();
0731:                proxyFactory.setProxyTargetClass(true);
0732:                proxyFactory.setFrozen(true);
0733:
0734:                if (isMBean(this .beanFactory.getType(beanName))) {
0735:                    // A straight MBean... Let's create a simple lazy-init CGLIB proxy for it.
0736:                    LazyInitTargetSource targetSource = new LazyInitTargetSource();
0737:                    targetSource.setTargetBeanName(beanName);
0738:                    targetSource.setBeanFactory(this .beanFactory);
0739:                    proxyFactory.setTargetSource(targetSource);
0740:
0741:                    Object proxy = proxyFactory.getProxy(this .beanClassLoader);
0742:                    ObjectName objectName = getObjectName(proxy, beanKey);
0743:                    if (logger.isDebugEnabled()) {
0744:                        logger
0745:                                .debug("Located MBean '"
0746:                                        + beanKey
0747:                                        + "': registering with JMX server as lazy-init MBean ["
0748:                                        + objectName + "]");
0749:                    }
0750:                    doRegister(proxy, objectName);
0751:                    return objectName;
0752:                }
0753:
0754:                else {
0755:                    // A simple bean... Let's create a lazy-init ModelMBean proxy with notification support.
0756:                    NotificationPublisherAwareLazyTargetSource targetSource = new NotificationPublisherAwareLazyTargetSource();
0757:                    targetSource.setTargetBeanName(beanName);
0758:                    targetSource.setBeanFactory(this .beanFactory);
0759:                    proxyFactory.setTargetSource(targetSource);
0760:
0761:                    Object proxy = proxyFactory.getProxy(this .beanClassLoader);
0762:                    ObjectName objectName = getObjectName(proxy, beanKey);
0763:                    if (logger.isDebugEnabled()) {
0764:                        logger
0765:                                .debug("Located simple bean '"
0766:                                        + beanKey
0767:                                        + "': registering with JMX server as lazy-init MBean ["
0768:                                        + objectName + "]");
0769:                    }
0770:                    ModelMBean mbean = createAndConfigureMBean(proxy, beanKey);
0771:                    targetSource.setModelMBean(mbean);
0772:                    targetSource.setObjectName(objectName);
0773:                    doRegister(mbean, objectName);
0774:                    return objectName;
0775:                }
0776:            }
0777:
0778:            /**
0779:             * Retrieve the <code>ObjectName</code> for a bean.
0780:             * <p>If the bean implements the <code>SelfNaming</code> interface, then the
0781:             * <code>ObjectName</code> will be retrieved using <code>SelfNaming.getObjectName()</code>.
0782:             * Otherwise, the configured <code>ObjectNamingStrategy</code> is used.
0783:             * @param bean the name of the bean in the <code>BeanFactory</code>
0784:             * @param beanKey the key associated with the bean in the beans map
0785:             * @return the <code>ObjectName</code> for the supplied bean
0786:             * @throws javax.management.MalformedObjectNameException
0787:             * if the retrieved <code>ObjectName</code> is malformed
0788:             */
0789:            protected ObjectName getObjectName(Object bean, String beanKey)
0790:                    throws MalformedObjectNameException {
0791:                if (bean instanceof  SelfNaming) {
0792:                    return ((SelfNaming) bean).getObjectName();
0793:                } else {
0794:                    return this .namingStrategy.getObjectName(bean, beanKey);
0795:                }
0796:            }
0797:
0798:            /**
0799:             * Determine whether the given bean class qualifies as an MBean as-is.
0800:             * <p>The default implementation delegates to {@link JmxUtils#isMBean},
0801:             * which checks for {@link javax.management.DynamicMBean} classes as well
0802:             * as classes with corresponding "*MBean" interface (Standard MBeans)
0803:             * or corresponding "*MXBean" interface (Java 6 MXBeans).
0804:             * @param beanClass the bean class to analyze
0805:             * @return whether the class qualifies as an MBean
0806:             * @see org.springframework.jmx.support.JmxUtils#isMBean(Class)
0807:             */
0808:            protected boolean isMBean(Class beanClass) {
0809:                return JmxUtils.isMBean(beanClass);
0810:            }
0811:
0812:            /**
0813:             * Build an adapted MBean for the given bean instance, if possible.
0814:             * <p>The default implementation builds a JMX 1.2 StandardMBean
0815:             * for the target's MBean/MXBean interface in case of an AOP proxy,
0816:             * delegating the interface's management operations to the proxy.
0817:             * @param bean the original bean instance
0818:             * @return the adapted MBean, or <code>null</code> if not possible
0819:             */
0820:            protected DynamicMBean adaptMBeanIfPossible(Object bean)
0821:                    throws JMException {
0822:                Class targetClass = AopUtils.getTargetClass(bean);
0823:                if (targetClass != bean.getClass()) {
0824:                    Class ifc = JmxUtils.getMXBeanInterface(targetClass);
0825:                    if (ifc != null) {
0826:                        if (!(ifc.isInstance(bean))) {
0827:                            throw new NotCompliantMBeanException(
0828:                                    "Managed bean ["
0829:                                            + bean
0830:                                            + "] has a target class with an MXBean interface but does not exposed it in the proxy");
0831:                        }
0832:                        return new StandardMBean(bean, ifc, true);
0833:                    } else {
0834:                        ifc = JmxUtils.getMBeanInterface(targetClass);
0835:                        if (ifc != null) {
0836:                            if (!(ifc.isInstance(bean))) {
0837:                                throw new NotCompliantMBeanException(
0838:                                        "Managed bean ["
0839:                                                + bean
0840:                                                + "] has a target class with an MXBean interface but does not exposed it in the proxy");
0841:                            }
0842:                            return new StandardMBean(bean, ifc);
0843:                        }
0844:                    }
0845:                }
0846:                return null;
0847:            }
0848:
0849:            /**
0850:             * Creates an MBean that is configured with the appropriate management
0851:             * interface for the supplied managed resource.
0852:             * @param managedResource the resource that is to be exported as an MBean
0853:             * @param beanKey the key associated with the managed bean
0854:             * @see #createModelMBean() 
0855:             * @see #getMBeanInfo(Object, String) 
0856:             */
0857:            protected ModelMBean createAndConfigureMBean(
0858:                    Object managedResource, String beanKey)
0859:                    throws MBeanExportException {
0860:                try {
0861:                    ModelMBean mbean = createModelMBean();
0862:                    mbean.setModelMBeanInfo(getMBeanInfo(managedResource,
0863:                            beanKey));
0864:                    mbean.setManagedResource(managedResource,
0865:                            MR_TYPE_OBJECT_REFERENCE);
0866:                    return mbean;
0867:                } catch (Exception ex) {
0868:                    throw new MBeanExportException(
0869:                            "Could not create ModelMBean for managed resource ["
0870:                                    + managedResource + "] with key '"
0871:                                    + beanKey + "'", ex);
0872:                }
0873:            }
0874:
0875:            /**
0876:             * Create an instance of a class that implements <code>ModelMBean</code>.
0877:             * <p>This method is called to obtain a <code>ModelMBean</code> instance to
0878:             * use when registering a bean. This method is called once per bean during the
0879:             * registration phase and must return a new instance of <code>ModelMBean</code>
0880:             * @return a new instance of a class that implements <code>ModelMBean</code>
0881:             * @throws javax.management.MBeanException if creation of the ModelMBean failed
0882:             */
0883:            protected ModelMBean createModelMBean() throws MBeanException {
0884:                return (this .exposeManagedResourceClassLoader ? new SpringModelMBean()
0885:                        : new RequiredModelMBean());
0886:            }
0887:
0888:            /**
0889:             * Gets the <code>ModelMBeanInfo</code> for the bean with the supplied key
0890:             * and of the supplied type.
0891:             */
0892:            private ModelMBeanInfo getMBeanInfo(Object managedBean,
0893:                    String beanKey) throws JMException {
0894:                ModelMBeanInfo info = this .assembler.getMBeanInfo(managedBean,
0895:                        beanKey);
0896:                if (logger.isWarnEnabled()
0897:                        && ObjectUtils.isEmpty(info.getAttributes())
0898:                        && ObjectUtils.isEmpty(info.getOperations())) {
0899:                    logger
0900:                            .warn("Bean with key '"
0901:                                    + beanKey
0902:                                    + "' has been registered as an MBean but has no exposed attributes or operations");
0903:                }
0904:                return info;
0905:            }
0906:
0907:            //---------------------------------------------------------------------
0908:            // Autodetection process
0909:            //---------------------------------------------------------------------
0910:
0911:            /**
0912:             * Invoked when using an <code>AutodetectCapableMBeanInfoAssembler</code>.
0913:             * Gives the assembler the opportunity to add additional beans from the
0914:             * <code>BeanFactory</code> to the list of beans to be exposed via JMX.
0915:             * <p>This implementation prevents a bean from being added to the list
0916:             * automatically if it has already been added manually, and it prevents
0917:             * certain internal classes from being registered automatically.
0918:             */
0919:            private void autodetectBeans(
0920:                    final AutodetectCapableMBeanInfoAssembler assembler) {
0921:                autodetect(new AutodetectCallback() {
0922:                    public boolean include(Class beanClass, String beanName) {
0923:                        return assembler.includeBean(beanClass, beanName);
0924:                    }
0925:                });
0926:            }
0927:
0928:            /**
0929:             * Attempts to detect any beans defined in the <code>ApplicationContext</code> that are
0930:             * valid MBeans and registers them automatically with the <code>MBeanServer</code>.
0931:             */
0932:            private void autodetectMBeans() {
0933:                autodetect(new AutodetectCallback() {
0934:                    public boolean include(Class beanClass, String beanName) {
0935:                        return isMBean(beanClass);
0936:                    }
0937:                });
0938:            }
0939:
0940:            /**
0941:             * Performs the actual autodetection process, delegating to an
0942:             * <code>AutodetectCallback</code> instance to vote on the inclusion of a
0943:             * given bean.
0944:             * @param callback the <code>AutodetectCallback</code> to use when deciding
0945:             * whether to include a bean or not
0946:             */
0947:            private void autodetect(AutodetectCallback callback) {
0948:                String[] beanNames = this .beanFactory.getBeanNamesForType(null);
0949:                for (int i = 0; i < beanNames.length; i++) {
0950:                    String beanName = beanNames[i];
0951:                    if (!isExcluded(beanName)) {
0952:                        Class beanClass = this .beanFactory.getType(beanName);
0953:                        if (beanClass != null
0954:                                && callback.include(beanClass, beanName)) {
0955:                            boolean lazyInit = isBeanDefinitionLazyInit(
0956:                                    this .beanFactory, beanName);
0957:                            Object beanInstance = (!lazyInit ? this .beanFactory
0958:                                    .getBean(beanName) : null);
0959:                            if (!this .beans.containsValue(beanName)
0960:                                    && (beanInstance == null || !CollectionUtils
0961:                                            .containsInstance(this .beans
0962:                                                    .values(), beanInstance))) {
0963:                                // Not already registered for JMX exposure.
0964:                                this .beans.put(beanName,
0965:                                        (beanInstance != null ? beanInstance
0966:                                                : beanName));
0967:                                if (logger.isInfoEnabled()) {
0968:                                    logger
0969:                                            .info("Bean with name '"
0970:                                                    + beanName
0971:                                                    + "' has been autodetected for JMX exposure");
0972:                                }
0973:                            } else {
0974:                                if (logger.isDebugEnabled()) {
0975:                                    logger
0976:                                            .debug("Bean with name '"
0977:                                                    + beanName
0978:                                                    + "' is already registered for JMX exposure");
0979:                                }
0980:                            }
0981:                        }
0982:                    }
0983:                }
0984:            }
0985:
0986:            /**
0987:             * Indicates whether or not a particular bean name is present in the excluded beans list.
0988:             */
0989:            private boolean isExcluded(String beanName) {
0990:                return (this .excludedBeans != null && this .excludedBeans
0991:                        .contains(beanName));
0992:            }
0993:
0994:            //---------------------------------------------------------------------
0995:            // Management of notification listeners
0996:            //---------------------------------------------------------------------
0997:
0998:            /**
0999:             * If the supplied managed resource implements the {@link NotificationPublisherAware} an instance of
1000:             * {@link org.springframework.jmx.export.notification.NotificationPublisher} is injected.
1001:             */
1002:            private void injectNotificationPublisherIfNecessary(
1003:                    Object managedResource, ModelMBean modelMBean,
1004:                    ObjectName objectName) {
1005:
1006:                if (managedResource instanceof  NotificationPublisherAware) {
1007:                    ((NotificationPublisherAware) managedResource)
1008:                            .setNotificationPublisher(new ModelMBeanNotificationPublisher(
1009:                                    modelMBean, objectName, managedResource));
1010:                }
1011:            }
1012:
1013:            /**
1014:             * Register the configured {@link NotificationListener NotificationListeners}
1015:             * with the {@link MBeanServer}.
1016:             */
1017:            private void registerNotificationListeners()
1018:                    throws MBeanExportException {
1019:                for (int i = 0; i < this .notificationListeners.length; i++) {
1020:                    NotificationListenerBean bean = this .notificationListeners[i];
1021:                    NotificationListener listener = bean
1022:                            .getNotificationListener();
1023:                    NotificationFilter filter = bean.getNotificationFilter();
1024:                    Object handback = bean.getHandback();
1025:                    ObjectName[] namesToRegisterWith = getObjectNamesForNotificationListener(bean);
1026:                    for (int j = 0; j < namesToRegisterWith.length; j++) {
1027:                        ObjectName objectName = namesToRegisterWith[j];
1028:                        try {
1029:                            this .server.addNotificationListener(objectName,
1030:                                    listener, filter, handback);
1031:                        } catch (InstanceNotFoundException ex) {
1032:                            throw new MBeanExportException(
1033:                                    "Unable to register NotificationListener for MBean ["
1034:                                            + objectName
1035:                                            + "] because that MBean instance does not exist",
1036:                                    ex);
1037:                        }
1038:                    }
1039:                }
1040:            }
1041:
1042:            /**
1043:             * Retrieve the {@link javax.management.ObjectName ObjectNames} for which a
1044:             * {@link NotificationListener} should be registered.
1045:             */
1046:            private ObjectName[] getObjectNamesForNotificationListener(
1047:                    NotificationListenerBean bean) throws MBeanExportException {
1048:
1049:                String[] mappedObjectNames = bean.getMappedObjectNames();
1050:                if (mappedObjectNames != null) {
1051:                    ObjectName[] objectNames = new ObjectName[mappedObjectNames.length];
1052:                    for (int i = 0; i < mappedObjectNames.length; i++) {
1053:                        String mappedName = mappedObjectNames[i];
1054:                        try {
1055:                            objectNames[i] = ObjectNameManager
1056:                                    .getInstance(mappedName);
1057:                        } catch (MalformedObjectNameException ex) {
1058:                            throw new MBeanExportException(
1059:                                    "Invalid ObjectName ["
1060:                                            + mappedName
1061:                                            + "] specified for NotificationListener ["
1062:                                            + bean.getNotificationListener()
1063:                                            + "]", ex);
1064:                        }
1065:                    }
1066:                    return objectNames;
1067:                } else {
1068:                    // Mapped to all MBeans registered by the MBeanExporter.
1069:                    return (ObjectName[]) this .registeredBeans
1070:                            .toArray(new ObjectName[this .registeredBeans.size()]);
1071:                }
1072:            }
1073:
1074:            /**
1075:             * Called when an MBean is registered. Notifies all registered
1076:             * {@link MBeanExporterListener MBeanExporterListeners} of the registration event.
1077:             * <p>Please note that if an {@link MBeanExporterListener} throws a (runtime)
1078:             * exception when notified, this will essentially interrupt the notification process
1079:             * and any remaining listeners that have yet to be notified will not (obviously)
1080:             * receive the {@link MBeanExporterListener#mbeanRegistered(javax.management.ObjectName)}
1081:             * callback.
1082:             * @param objectName the <code>ObjectName</code> of the registered MBean
1083:             */
1084:            protected void onRegister(ObjectName objectName) {
1085:                notifyListenersOfRegistration(objectName);
1086:            }
1087:
1088:            /**
1089:             * Called when an MBean is unregistered. Notifies all registered
1090:             * {@link MBeanExporterListener MBeanExporterListeners} of the unregistration event.
1091:             * <p>Please note that if an {@link MBeanExporterListener} throws a (runtime)
1092:             * exception when notified, this will essentially interrupt the notification process
1093:             * and any remaining listeners that have yet to be notified will not (obviously)
1094:             * receive the {@link MBeanExporterListener#mbeanUnregistered(javax.management.ObjectName)}
1095:             * callback.
1096:             * @param objectName the <code>ObjectName</code> of the unregistered MBean
1097:             */
1098:            protected void onUnregister(ObjectName objectName) {
1099:                notifyListenersOfUnregistration(objectName);
1100:            }
1101:
1102:            /**
1103:             * Notifies all registered {@link MBeanExporterListener MBeanExporterListeners} of the
1104:             * registration of the MBean identified by the supplied {@link ObjectName}.
1105:             */
1106:            private void notifyListenersOfRegistration(ObjectName objectName) {
1107:                if (this .listeners != null) {
1108:                    for (int i = 0; i < this .listeners.length; i++) {
1109:                        this .listeners[i].mbeanRegistered(objectName);
1110:                    }
1111:                }
1112:            }
1113:
1114:            /**
1115:             * Notifies all registered {@link MBeanExporterListener MBeanExporterListeners} of the
1116:             * unregistration of the MBean identified by the supplied {@link ObjectName}.
1117:             */
1118:            private void notifyListenersOfUnregistration(ObjectName objectName) {
1119:                if (this .listeners != null) {
1120:                    for (int i = 0; i < this .listeners.length; i++) {
1121:                        this .listeners[i].mbeanUnregistered(objectName);
1122:                    }
1123:                }
1124:            }
1125:
1126:            //---------------------------------------------------------------------
1127:            // Inner classes for internal use
1128:            //---------------------------------------------------------------------
1129:
1130:            /**
1131:             * Internal callback interface for the autodetection process.
1132:             */
1133:            private static interface AutodetectCallback {
1134:
1135:                /**
1136:                 * Called during the autodetection process to decide whether
1137:                 * or not a bean should be included.
1138:                 * @param beanClass the class of the bean
1139:                 * @param beanName the name of the bean
1140:                 */
1141:                boolean include(Class beanClass, String beanName);
1142:            }
1143:
1144:            /**
1145:             * Extension of {@link LazyInitTargetSource} that will inject a
1146:             * {@link org.springframework.jmx.export.notification.NotificationPublisher}
1147:             * into the lazy resource as it is created if required.
1148:             */
1149:            private class NotificationPublisherAwareLazyTargetSource extends
1150:                    LazyInitTargetSource {
1151:
1152:                private ModelMBean modelMBean;
1153:
1154:                private ObjectName objectName;
1155:
1156:                public void setModelMBean(ModelMBean modelMBean) {
1157:                    this .modelMBean = modelMBean;
1158:                }
1159:
1160:                public void setObjectName(ObjectName objectName) {
1161:                    this .objectName = objectName;
1162:                }
1163:
1164:                protected void postProcessTargetObject(Object targetObject) {
1165:                    injectNotificationPublisherIfNecessary(targetObject,
1166:                            this.modelMBean, this.objectName);
1167:                }
1168:            }
1169:
1170:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.