View Javadoc

1   /*
2    * $Id: JmxAgent.java 20203 2010-11-17 01:54:38Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  package org.mule.module.management.agent;
11  
12  import org.mule.AbstractAgent;
13  import org.mule.api.MuleException;
14  import org.mule.api.MuleRuntimeException;
15  import org.mule.api.context.notification.MuleContextNotificationListener;
16  import org.mule.api.lifecycle.InitialisationException;
17  import org.mule.api.model.Model;
18  import org.mule.api.service.Service;
19  import org.mule.api.transport.Connector;
20  import org.mule.api.transport.MessageReceiver;
21  import org.mule.config.i18n.CoreMessages;
22  import org.mule.construct.AbstractFlowConstruct;
23  import org.mule.context.notification.MuleContextNotification;
24  import org.mule.context.notification.NotificationException;
25  import org.mule.module.management.i18n.ManagementMessages;
26  import org.mule.module.management.mbean.ConnectorService;
27  import org.mule.module.management.mbean.ConnectorServiceMBean;
28  import org.mule.module.management.mbean.EndpointService;
29  import org.mule.module.management.mbean.EndpointServiceMBean;
30  import org.mule.module.management.mbean.FlowConstructService;
31  import org.mule.module.management.mbean.FlowConstructServiceMBean;
32  import org.mule.module.management.mbean.ModelService;
33  import org.mule.module.management.mbean.ModelServiceMBean;
34  import org.mule.module.management.mbean.MuleConfigurationService;
35  import org.mule.module.management.mbean.MuleConfigurationServiceMBean;
36  import org.mule.module.management.mbean.MuleService;
37  import org.mule.module.management.mbean.MuleServiceMBean;
38  import org.mule.module.management.mbean.ServiceService;
39  import org.mule.module.management.mbean.ServiceServiceMBean;
40  import org.mule.module.management.mbean.StatisticsService;
41  import org.mule.module.management.mbean.StatisticsServiceMBean;
42  import org.mule.module.management.support.AutoDiscoveryJmxSupportFactory;
43  import org.mule.module.management.support.JmxSupport;
44  import org.mule.module.management.support.JmxSupportFactory;
45  import org.mule.module.management.support.SimplePasswordJmxAuthenticator;
46  import org.mule.transport.AbstractConnector;
47  import org.mule.util.ClassUtils;
48  import org.mule.util.StringUtils;
49  
50  import java.lang.management.ManagementFactory;
51  import java.net.URI;
52  import java.rmi.RemoteException;
53  import java.rmi.registry.LocateRegistry;
54  import java.rmi.registry.Registry;
55  import java.rmi.server.ExportException;
56  import java.util.Collections;
57  import java.util.HashMap;
58  import java.util.Map;
59  import java.util.Set;
60  
61  import javax.management.InstanceAlreadyExistsException;
62  import javax.management.MBeanRegistrationException;
63  import javax.management.MBeanServer;
64  import javax.management.MBeanServerFactory;
65  import javax.management.MalformedObjectNameException;
66  import javax.management.NotCompliantMBeanException;
67  import javax.management.ObjectName;
68  import javax.management.remote.JMXAuthenticator;
69  import javax.management.remote.JMXConnectorServer;
70  import javax.management.remote.JMXConnectorServerFactory;
71  import javax.management.remote.JMXServiceURL;
72  import javax.management.remote.rmi.RMIConnectorServer;
73  
74  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
75  
76  import org.apache.commons.logging.Log;
77  import org.apache.commons.logging.LogFactory;
78  
79  /**
80   * <code>JmxAgent</code> registers Mule Jmx management beans with an MBean server.
81   */
82  public class JmxAgent extends AbstractAgent
83  {
84      public static final String NAME = "jmx-agent";
85  
86      public static final String DEFAULT_REMOTING_URI = "service:jmx:rmi:///jndi/rmi://localhost:1099/server";
87      
88      // populated with values below in a static initializer
89      public static final Map<String, String> DEFAULT_CONNECTOR_SERVER_PROPERTIES;
90  
91      /**
92       * Default JMX Authenticator to use for securing remote access.
93       */
94      public static final String DEFAULT_JMX_AUTHENTICATOR = SimplePasswordJmxAuthenticator.class.getName();
95  
96      /**
97       * Logger used by this class
98       */
99      protected static final Log logger = LogFactory.getLog(JmxAgent.class);
100 
101     /**
102      * Should MBeanServer be discovered.
103      */
104     protected boolean locateServer = true;
105 
106     protected boolean containerMode = true;
107 
108     // don't create mbean server by default, use a platform mbean server
109     private boolean createServer = false;
110     private String connectorServerUrl;
111     private MBeanServer mBeanServer;
112     private JMXConnectorServer connectorServer;
113     private Map<String, Object> connectorServerProperties = null;
114     private boolean enableStatistics = true;
115     private final AtomicBoolean serverCreated = new AtomicBoolean(false);
116     private final AtomicBoolean initialized = new AtomicBoolean(false);
117 
118     private JmxSupportFactory jmxSupportFactory = AutoDiscoveryJmxSupportFactory.getInstance();
119     private JmxSupport jmxSupport = jmxSupportFactory.getJmxSupport();
120 
121     //Used is RMI is being used
122     private Registry rmiRegistry;
123     private boolean createRmiRegistry = true;
124     /**
125      * Username/password combinations for JMX Remoting authentication.
126      */
127     private Map<String, String> credentials = new HashMap<String, String>();
128 
129     static
130     {
131         Map<String, String> props = new HashMap<String, String>(1);
132         props.put(RMIConnectorServer.JNDI_REBIND_ATTRIBUTE, "true");
133         DEFAULT_CONNECTOR_SERVER_PROPERTIES = Collections.unmodifiableMap(props);
134     }
135 
136     public JmxAgent()
137     {
138         super(NAME);
139         connectorServerProperties = new HashMap<String, Object>(DEFAULT_CONNECTOR_SERVER_PROPERTIES);
140     }
141 
142     @Override
143     public String getDescription()
144     {
145         if (connectorServerUrl != null)
146         {
147             return name + ": " + connectorServerUrl;
148         }
149         else
150         {
151             return "JMX Agent";
152         }
153     }
154 
155     /**
156      * {@inheritDoc}
157      */
158     public void initialise() throws InitialisationException
159     {
160         if (initialized.get())
161         {
162             return;
163         }
164 
165         this.containerMode = muleContext.getConfiguration().isContainerMode();
166 
167         try
168         {
169             Object agent = muleContext.getRegistry().lookupObject(this.getClass());
170             // if we find ourselves, but not initialized yet - proceed with init, otherwise return
171             if (agent == this && this.initialized.get())
172             {
173                 if (logger.isDebugEnabled())
174                 {
175                     logger.debug("Found an existing JMX agent in the registry, we're done here.");
176                 }
177                 return;
178             }
179         }
180         catch (Exception e)
181         {
182             throw new InitialisationException(e, this);
183         }
184 
185 
186         if (mBeanServer == null && createServer)
187         {
188             // here we create a new mbean server, not using a platform one
189             mBeanServer = MBeanServerFactory.createMBeanServer();
190             serverCreated.set(true);
191         }
192 
193         if (mBeanServer == null && locateServer)
194         {
195             mBeanServer = ManagementFactory.getPlatformMBeanServer();
196         }
197 
198         if (mBeanServer == null)
199         {
200             throw new InitialisationException(ManagementMessages.cannotLocateOrCreateServer(), this);
201         }
202 
203         if (StringUtils.isBlank(muleContext.getConfiguration().getId()))
204         {
205             // TODO i18n the message properly
206             throw new IllegalArgumentException(
207                     "Manager ID is mandatory when running with JmxAgent. Give your Mule configuration a valid ID.");
208         }
209 
210         try
211         {
212             // We need to register all the services once the server has initialised
213             muleContext.registerListener(new MuleContextStartedListener());
214             // and unregister once context stopped
215             muleContext.registerListener(new MuleContextStoppedListener());
216         }
217         catch (NotificationException e)
218         {
219             throw new InitialisationException(e, this);
220         }
221         initialized.compareAndSet(false, true);
222     }
223 
224     protected void initRMI() throws Exception
225     {
226         String connectUri = (connectorServerUrl != null ? connectorServerUrl : DEFAULT_REMOTING_URI);
227         if (connectUri.contains("jmx:rmi"))
228         {
229             int i = connectUri.lastIndexOf("rmi://");
230             URI uri = new URI(connectUri.substring(i));
231             if (rmiRegistry == null)
232             {
233                 try
234                 {
235                     if (isCreateRmiRegistry())
236                     {
237                         try
238                         {
239                             rmiRegistry = LocateRegistry.createRegistry(uri.getPort());
240                         }
241                         catch (ExportException e)
242                         {
243                             logger.info("Registry on " + uri  + " already bound. Attempting to use that instead");
244                             rmiRegistry = LocateRegistry.getRegistry(uri.getHost(), uri.getPort());
245                         }
246                     }
247                     else
248                     {
249                         rmiRegistry = LocateRegistry.getRegistry(uri.getHost(), uri.getPort());
250                     }
251                 }
252                 catch (RemoteException e)
253                 {
254                     throw new InitialisationException(e, this);
255                 }
256             }
257         }
258     }
259 
260     public void start() throws MuleException
261     {
262         try
263         {
264             // TODO cleanup rmi registry creation too
265             initRMI();
266             if (connectorServerUrl == null)
267             {
268                 return;
269             }
270 
271             logger.info("Creating and starting JMX agent connector Server");
272             JMXServiceURL url = new JMXServiceURL(connectorServerUrl);
273             if (connectorServerProperties == null)
274             {
275                 connectorServerProperties = new HashMap<String, Object>(DEFAULT_CONNECTOR_SERVER_PROPERTIES);
276             }
277             // TODO custom authenticator may have its own security config,
278             // refactor
279             if (!credentials.isEmpty())
280             {
281                 JMXAuthenticator jmxAuthenticator = (JMXAuthenticator) ClassUtils.instanciateClass(DEFAULT_JMX_AUTHENTICATOR);
282                 // TODO support for custom authenticators
283                 ((SimplePasswordJmxAuthenticator) jmxAuthenticator).setCredentials(credentials);
284                 connectorServerProperties.put(JMXConnectorServer.AUTHENTICATOR, jmxAuthenticator);
285             }
286             connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url,
287                                                                               connectorServerProperties,
288                                                                               mBeanServer);
289             connectorServer.start();
290         }
291         catch (ExportException e)
292         {
293             throw new JmxManagementException(CoreMessages.failedToStart("Jmx Agent"), e);
294         }
295         catch (Exception e)
296         {
297             throw new JmxManagementException(CoreMessages.failedToStart("Jmx Agent"), e);
298         }
299     }
300 
301     public void stop() throws MuleException
302     {
303         if (connectorServer != null)
304         {
305             try
306             {
307                 connectorServer.stop();
308             }
309             catch (Exception e)
310             {
311                 throw new JmxManagementException(CoreMessages.failedToStop("Jmx Connector"), e);
312             }
313         }
314     }
315 
316     /**
317      * {@inheritDoc}
318      */
319     public void dispose()
320     {
321         unregisterMBeansIfNecessary();
322         if (serverCreated.get())
323         {
324             MBeanServerFactory.releaseMBeanServer(mBeanServer);
325         }
326         mBeanServer = null;
327         serverCreated.compareAndSet(true, false);
328         initialized.set(false);
329     }
330 
331     /**
332      * Register a Java Service Wrapper agent.
333      *
334      * @throws MuleException if registration failed
335      */
336     protected void registerWrapperService() throws MuleException
337     {
338         // WrapperManager to support restarts
339         final WrapperManagerAgent wmAgent = new WrapperManagerAgent();
340         if (muleContext.getRegistry().lookupAgent(wmAgent.getName()) == null)
341         {
342             muleContext.getRegistry().registerAgent(wmAgent);
343         }
344     }
345 
346     protected void registerStatisticsService() throws NotCompliantMBeanException, MBeanRegistrationException,
347         InstanceAlreadyExistsException, MalformedObjectNameException
348     {
349         ObjectName on = jmxSupport.getObjectName(String.format("%s:%s", jmxSupport.getDomainName(muleContext, !containerMode), StatisticsServiceMBean.DEFAULT_JMX_NAME));
350         StatisticsService service = new StatisticsService();
351         service.setMuleContext(muleContext);
352         service.setEnabled(isEnableStatistics());
353         ClassloaderSwitchingMBeanWrapper mBean = new ClassloaderSwitchingMBeanWrapper(service, StatisticsServiceMBean.class, muleContext.getExecutionClassLoader());
354         logger.debug("Registering statistics with name: " + on);
355         mBeanServer.registerMBean(mBean, on);
356     }
357 
358     protected void registerModelServices() throws NotCompliantMBeanException, MBeanRegistrationException,
359             InstanceAlreadyExistsException, MalformedObjectNameException
360     {
361         for (Model model : muleContext.getRegistry().lookupObjects(Model.class))
362         {
363             ModelServiceMBean service = new ModelService(model);
364             String rawName = service.getName() + "(" + service.getType() + ")";
365             String name = jmxSupport.escape(rawName);
366             final String jmxName = String.format("%s:%s%s", jmxSupport.getDomainName(muleContext, !containerMode), ModelServiceMBean.DEFAULT_JMX_NAME_PREFIX, name);
367             ObjectName on = jmxSupport.getObjectName(jmxName);
368             ClassloaderSwitchingMBeanWrapper mBean = new ClassloaderSwitchingMBeanWrapper(service, ModelServiceMBean.class, muleContext.getExecutionClassLoader());
369             logger.debug("Registering model with name: " + on);
370             mBeanServer.registerMBean(mBean, on);
371         }
372     }
373 
374     protected void registerMuleService() throws NotCompliantMBeanException, MBeanRegistrationException,
375         InstanceAlreadyExistsException, MalformedObjectNameException
376     {
377         ObjectName on = jmxSupport.getObjectName(String.format("%s:%s", jmxSupport.getDomainName(muleContext, !containerMode), MuleServiceMBean.DEFAULT_JMX_NAME));
378         if (muleContext.getConfiguration().isContainerMode() && mBeanServer.isRegistered(on))
379         {
380             // while in container mode, a previous stop() action leaves MuleContext MBean behind for remote start() operation
381             return;
382         }
383         MuleService service = new MuleService(muleContext);
384         ClassloaderSwitchingMBeanWrapper serviceMBean = new ClassloaderSwitchingMBeanWrapper(service, MuleServiceMBean.class, muleContext.getExecutionClassLoader());
385         logger.debug("Registering mule with name: " + on);
386         mBeanServer.registerMBean(serviceMBean, on);
387     }
388 
389     protected void registerConfigurationService() throws NotCompliantMBeanException, MBeanRegistrationException,
390             InstanceAlreadyExistsException, MalformedObjectNameException
391     {
392         ObjectName on = jmxSupport.getObjectName(String.format("%s:%s", jmxSupport.getDomainName(muleContext, !containerMode), MuleConfigurationServiceMBean.DEFAULT_JMX_NAME));
393         MuleConfigurationServiceMBean service = new MuleConfigurationService(muleContext.getConfiguration());
394         ClassloaderSwitchingMBeanWrapper mBean = new ClassloaderSwitchingMBeanWrapper(service, MuleConfigurationServiceMBean.class, muleContext.getExecutionClassLoader());
395         logger.debug("Registering configuration with name: " + on);
396         mBeanServer.registerMBean(mBean, on);
397     }
398 
399     protected void registerServiceServices() throws NotCompliantMBeanException, MBeanRegistrationException,
400         InstanceAlreadyExistsException, MalformedObjectNameException
401     {
402         for (Service service : muleContext.getRegistry().lookupObjects(Service.class))
403         {
404             final String rawName = service.getName();
405             final String name = jmxSupport.escape(rawName);
406             final String jmxName = String.format("%s:%s%s", jmxSupport.getDomainName(muleContext, !containerMode), ServiceServiceMBean.DEFAULT_JMX_NAME_PREFIX, name);
407             ObjectName on = jmxSupport.getObjectName(jmxName);
408             ServiceServiceMBean serviceMBean = new ServiceService(rawName, muleContext);
409             ClassloaderSwitchingMBeanWrapper wrapper = new ClassloaderSwitchingMBeanWrapper(serviceMBean, ServiceServiceMBean.class, muleContext.getExecutionClassLoader());
410             logger.debug("Registering service with name: " + on);
411             mBeanServer.registerMBean(wrapper, on);
412         }
413     }
414 
415     protected void registerFlowConstructServices() throws NotCompliantMBeanException, MBeanRegistrationException,
416         InstanceAlreadyExistsException, MalformedObjectNameException
417     {
418         for (AbstractFlowConstruct flowConstruct : muleContext.getRegistry().lookupObjects(AbstractFlowConstruct.class))
419         {
420             final String rawName = flowConstruct.getName();
421             final String name = jmxSupport.escape(rawName);
422             final String jmxName = String.format("%s:type=%s,name=%s", jmxSupport.getDomainName(muleContext, !containerMode), flowConstruct.getConstructType(), name);
423             ObjectName on = jmxSupport.getObjectName(jmxName);
424             FlowConstructServiceMBean fcMBean = new FlowConstructService(flowConstruct.getConstructType(), rawName, muleContext, flowConstruct.getStatistics());
425             ClassloaderSwitchingMBeanWrapper wrapper = new ClassloaderSwitchingMBeanWrapper(fcMBean, FlowConstructServiceMBean.class, muleContext.getExecutionClassLoader());
426             logger.debug("Registering service with name: " + on);
427             mBeanServer.registerMBean(wrapper, on);
428         }
429     }
430 
431     protected void registerEndpointServices() throws NotCompliantMBeanException, MBeanRegistrationException,
432         InstanceAlreadyExistsException, MalformedObjectNameException
433     {
434         for (Connector connector : muleContext.getRegistry().lookupObjects(Connector.class))
435         {
436             if (connector instanceof AbstractConnector)
437             {
438                 for (MessageReceiver messageReceiver : ((AbstractConnector) connector).getReceivers().values())
439                 {
440                     EndpointServiceMBean service = new EndpointService(messageReceiver);
441 
442                     String fullName = buildFullyQualifiedEndpointName(service, connector);
443                     if (logger.isInfoEnabled())
444                     {
445                         logger.info("Attempting to register service with name: " + fullName);
446                     }
447 
448                     ObjectName on = jmxSupport.getObjectName(fullName);
449                     ClassloaderSwitchingMBeanWrapper mBean = new ClassloaderSwitchingMBeanWrapper(service, EndpointServiceMBean.class, muleContext.getExecutionClassLoader());
450                     mBeanServer.registerMBean(mBean, on);
451                     if (logger.isInfoEnabled())
452                     {
453                         logger.info("Registered Endpoint Service with name: " + on);
454                     }
455                 }
456             }
457             else
458             {
459                 logger.warn("Connector: " + connector
460                         + " is not an istance of AbstractConnector, cannot obtain Endpoint MBeans from it");
461             }
462         }
463     }
464 
465     protected String buildFullyQualifiedEndpointName(EndpointServiceMBean mBean, Connector connector)
466     {
467         String rawName = jmxSupport.escape(mBean.getName());
468 
469         StringBuilder fullName = new StringBuilder(128);
470         fullName.append(jmxSupport.getDomainName(muleContext, !containerMode));
471         fullName.append(":type=Endpoint,service=");
472         fullName.append(jmxSupport.escape(mBean.getComponentName()));
473         fullName.append(",connector=");
474         fullName.append(connector.getName());
475         fullName.append(",name=");
476         fullName.append(rawName);
477         return fullName.toString();
478     }
479 
480     protected void registerConnectorServices() throws MalformedObjectNameException,
481         NotCompliantMBeanException, MBeanRegistrationException, InstanceAlreadyExistsException
482     {
483         for (Connector connector : muleContext.getRegistry().lookupObjects(Connector.class))
484         {
485             ConnectorServiceMBean service = new ConnectorService(connector);
486             final String rawName = service.getName();
487             final String name = jmxSupport.escape(rawName);
488             final String jmxName = String.format("%s:%s%s", jmxSupport.getDomainName(muleContext, !containerMode), ConnectorServiceMBean.DEFAULT_JMX_NAME_PREFIX, name);
489             if (logger.isDebugEnabled())
490             {
491                 logger.debug("Attempting to register service with name: " + jmxName);
492             }
493             ObjectName oName = jmxSupport.getObjectName(jmxName);
494             ClassloaderSwitchingMBeanWrapper mBean = new ClassloaderSwitchingMBeanWrapper(service, ConnectorServiceMBean.class, muleContext.getExecutionClassLoader());
495             mBeanServer.registerMBean(mBean, oName);
496             logger.info("Registered Connector Service with name " + oName);
497         }
498     }
499 
500     public boolean isCreateServer()
501     {
502         return createServer;
503     }
504 
505     public void setCreateServer(boolean createServer)
506     {
507         this.createServer = createServer;
508     }
509 
510     public boolean isLocateServer()
511     {
512         return locateServer;
513     }
514 
515     public void setLocateServer(boolean locateServer)
516     {
517         this.locateServer = locateServer;
518     }
519 
520     public String getConnectorServerUrl()
521     {
522         return connectorServerUrl;
523     }
524 
525     public void setConnectorServerUrl(String connectorServerUrl)
526     {
527         this.connectorServerUrl = connectorServerUrl;
528     }
529 
530     public boolean isEnableStatistics()
531     {
532         return enableStatistics;
533     }
534 
535     public void setEnableStatistics(boolean enableStatistics)
536     {
537         this.enableStatistics = enableStatistics;
538     }
539 
540     public MBeanServer getMBeanServer()
541     {
542         return mBeanServer;
543     }
544 
545     public void setMBeanServer(MBeanServer mBeanServer)
546     {
547         this.mBeanServer = mBeanServer;
548     }
549 
550     public Map<String, Object> getConnectorServerProperties()
551     {
552         return connectorServerProperties;
553     }
554 
555     /**
556      * Setter for property 'connectorServerProperties'. Set to {@code null} to use defaults ({@link
557      * #DEFAULT_CONNECTOR_SERVER_PROPERTIES}). Pass in an empty map to use no parameters.
558      * Passing a non-empty map will replace defaults.
559      *
560      * @param connectorServerProperties Value to set for property 'connectorServerProperties'.
561      */
562     public void setConnectorServerProperties(Map<String, Object> connectorServerProperties)
563     {
564         this.connectorServerProperties = connectorServerProperties;
565     }
566 
567     public JmxSupportFactory getJmxSupportFactory()
568     {
569         return jmxSupportFactory;
570     }
571 
572     public void setJmxSupportFactory(JmxSupportFactory jmxSupportFactory)
573     {
574         this.jmxSupportFactory = jmxSupportFactory;
575     }
576 
577 
578     /**
579      * Setter for property 'credentials'.
580      *
581      * @param newCredentials Value to set for property 'credentials'.
582      */
583     public void setCredentials(final Map<String, String> newCredentials)
584     {
585         this.credentials.clear();
586         if (newCredentials != null && !newCredentials.isEmpty())
587         {
588             this.credentials.putAll(newCredentials);
589         }
590     }
591 
592     protected void unregisterMBeansIfNecessary()
593     {
594         unregisterMBeansIfNecessary(false);
595     }
596 
597     /**
598      * @param containerMode when true, MuleContext will still be exposed to enable the 'start' operation
599      */
600     protected void unregisterMBeansIfNecessary(boolean containerMode)
601     {
602         if (mBeanServer == null)
603         {
604             return;
605         }
606 
607         try
608         {
609             // note that we don't try to resolve a domain name clash here.
610             // e.g. when stopping an app via jmx, we want to obtain current domain only,
611             // but the execution thread is different, and doesn't have the resolved domain info 
612             final String domain = jmxSupport.getDomainName(muleContext, false);
613             ObjectName query = jmxSupport.getObjectName(domain + ":*");
614             Set<ObjectName> mbeans = mBeanServer.queryNames(query, null);
615             while (!mbeans.isEmpty())
616             {
617                 ObjectName name = mbeans.iterator().next();
618                 try
619                 {
620                     if (!(containerMode && MuleServiceMBean.DEFAULT_JMX_NAME.equals(name.getCanonicalKeyPropertyListString())))
621                     {
622                         mBeanServer.unregisterMBean(name);
623                     }
624                 }
625                 catch (Exception e)
626                 {
627                     logger.warn(String.format("Failed to unregister MBean: %s. Error is: %s", name, e.getMessage()));
628                 }
629 
630                 // query mbeans again, as some mbeans have cascaded unregister operations,
631                 // this prevents duplicate unregister attempts
632                 mbeans = mBeanServer.queryNames(query, null);
633 
634                 if (containerMode)
635                 {
636                     // filter out MuleContext MBean to avoid an endless loop
637                     mbeans.remove(jmxSupport.getObjectName(String.format("%s:%s", domain, MuleServiceMBean.DEFAULT_JMX_NAME)));
638                 }
639             }
640         }
641         catch (MalformedObjectNameException e)
642         {
643             logger.warn("Failed to create ObjectName query", e);
644         }
645     }
646 
647     public Registry getRmiRegistry()
648     {
649         return rmiRegistry;
650     }
651 
652     public void setRmiRegistry(Registry rmiRegistry)
653     {
654         this.rmiRegistry = rmiRegistry;
655     }
656 
657     public boolean isCreateRmiRegistry()
658     {
659         return createRmiRegistry;
660     }
661 
662     public void setCreateRmiRegistry(boolean createRmiRegistry)
663     {
664         this.createRmiRegistry = createRmiRegistry;
665     }
666 
667     protected class MuleContextStartedListener implements MuleContextNotificationListener<MuleContextNotification>
668     {
669 
670         public void onNotification(MuleContextNotification notification)
671         {
672             if (notification.getAction() == MuleContextNotification.CONTEXT_STARTED)
673             {
674                 try
675                 {
676                     registerWrapperService();
677                     registerStatisticsService();
678                     registerMuleService();
679                     registerConfigurationService();
680                     registerModelServices();
681                     registerServiceServices();
682                     registerFlowConstructServices();
683                     registerEndpointServices();
684                     registerConnectorServices();
685                 }
686                 catch (Exception e)
687                 {
688                     throw new MuleRuntimeException(CoreMessages.objectFailedToInitialise("MBeans"), e);
689                 }
690             }
691         }
692     }
693 
694     protected class MuleContextStoppedListener implements MuleContextNotificationListener<MuleContextNotification>
695     {
696 
697         public void onNotification(MuleContextNotification notification)
698         {
699             if (notification.getAction() == MuleContextNotification.CONTEXT_STOPPED)
700             {
701                 boolean containerMode = notification.getMuleContext().getConfiguration().isContainerMode();
702                 unregisterMBeansIfNecessary(containerMode);
703             }
704         }
705     }
706 }