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