View Javadoc

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