1
2
3
4
5
6
7
8
9
10 package org.mule.management.agents;
11
12 import org.mule.MuleManager;
13 import org.mule.MuleRuntimeException;
14 import org.mule.config.i18n.CoreMessages;
15 import org.mule.impl.internal.notifications.ManagerNotification;
16 import org.mule.impl.internal.notifications.ManagerNotificationListener;
17 import org.mule.impl.internal.notifications.NotificationException;
18 import org.mule.management.i18n.ManagementMessages;
19 import org.mule.management.mbeans.ComponentService;
20 import org.mule.management.mbeans.ComponentServiceMBean;
21 import org.mule.management.mbeans.ConnectorService;
22 import org.mule.management.mbeans.ConnectorServiceMBean;
23 import org.mule.management.mbeans.EndpointService;
24 import org.mule.management.mbeans.EndpointServiceMBean;
25 import org.mule.management.mbeans.ModelService;
26 import org.mule.management.mbeans.ModelServiceMBean;
27 import org.mule.management.mbeans.MuleConfigurationService;
28 import org.mule.management.mbeans.MuleConfigurationServiceMBean;
29 import org.mule.management.mbeans.MuleService;
30 import org.mule.management.mbeans.MuleServiceMBean;
31 import org.mule.management.mbeans.StatisticsService;
32 import org.mule.management.support.AutoDiscoveryJmxSupportFactory;
33 import org.mule.management.support.JmxSupport;
34 import org.mule.management.support.JmxSupportFactory;
35 import org.mule.management.support.SimplePasswordJmxAuthenticator;
36 import org.mule.providers.AbstractConnector;
37 import org.mule.umo.UMOException;
38 import org.mule.umo.lifecycle.InitialisationException;
39 import org.mule.umo.manager.UMOAgent;
40 import org.mule.umo.manager.UMOManager;
41 import org.mule.umo.manager.UMOServerNotification;
42 import org.mule.umo.model.UMOModel;
43 import org.mule.umo.provider.UMOConnector;
44 import org.mule.umo.provider.UMOMessageReceiver;
45 import org.mule.util.ClassUtils;
46 import org.mule.util.StringUtils;
47
48 import java.util.ArrayList;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.Iterator;
52 import java.util.List;
53 import java.util.Map;
54
55 import javax.management.InstanceAlreadyExistsException;
56 import javax.management.MBeanRegistrationException;
57 import javax.management.MBeanServer;
58 import javax.management.MBeanServerFactory;
59 import javax.management.MalformedObjectNameException;
60 import javax.management.NotCompliantMBeanException;
61 import javax.management.ObjectName;
62 import javax.management.remote.JMXAuthenticator;
63 import javax.management.remote.JMXConnectorServer;
64 import javax.management.remote.JMXConnectorServerFactory;
65 import javax.management.remote.JMXServiceURL;
66 import javax.management.remote.rmi.RMIConnectorServer;
67
68 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
69 import org.apache.commons.logging.Log;
70 import org.apache.commons.logging.LogFactory;
71
72
73
74
75
76 public class JmxAgent implements UMOAgent
77 {
78 public static final String DEFAULT_REMOTING_URI = "service:jmx:rmi:///jndi/rmi://localhost:1099/server";
79
80 public static final Map DEFAULT_CONNECTOR_SERVER_PROPERTIES;
81
82
83
84
85 public static final String DEFAULT_JMX_AUTHENTICATOR = SimplePasswordJmxAuthenticator.class.getName();
86
87
88
89
90 protected static final Log logger = LogFactory.getLog(JmxAgent.class);
91
92
93
94
95 protected boolean locateServer = true;
96
97 private String name = "JMX Agent";
98 private boolean createServer = true;
99 private String connectorServerUrl;
100 private MBeanServer mBeanServer;
101 private JMXConnectorServer connectorServer;
102 private Map connectorServerProperties = null;
103 private boolean enableStatistics = true;
104 private List registeredMBeans = new ArrayList();
105 private final AtomicBoolean serverCreated = new AtomicBoolean(false);
106 private final AtomicBoolean initialized = new AtomicBoolean(false);
107
108 private JmxSupportFactory jmxSupportFactory = AutoDiscoveryJmxSupportFactory.getInstance();
109 private JmxSupport jmxSupport = jmxSupportFactory.getJmxSupport();
110
111
112
113
114 public JmxAgent ()
115 {
116 connectorServerProperties = new HashMap(DEFAULT_CONNECTOR_SERVER_PROPERTIES);
117 }
118
119
120
121
122
123 private Map credentials = new HashMap();
124
125 static {
126 Map props = new HashMap(1);
127 props.put(RMIConnectorServer.JNDI_REBIND_ATTRIBUTE, "true");
128 DEFAULT_CONNECTOR_SERVER_PROPERTIES = Collections.unmodifiableMap(props);
129 }
130
131
132
133
134
135 public String getName()
136 {
137 return this.name;
138 }
139
140
141
142
143
144 public void setName(String name)
145 {
146 this.name = name;
147 }
148
149
150
151
152
153 public String getDescription()
154 {
155 if (connectorServerUrl != null)
156 {
157 return "JMX Agent: " + connectorServerUrl;
158 }
159 else
160 {
161 return "JMX Agent";
162 }
163 }
164
165
166
167
168
169
170 public void initialise() throws InitialisationException
171 {
172 if (initialized.get()) {
173 return;
174 }
175 if (mBeanServer == null && !locateServer && !createServer) {
176 throw new InitialisationException(ManagementMessages.createOrLocateShouldBeSet(), this);
177 }
178 if (mBeanServer == null && locateServer) {
179 List l = MBeanServerFactory.findMBeanServer(null);
180 if (l != null && l.size() > 0) {
181 mBeanServer = (MBeanServer) l.get(0);
182 }
183 }
184 if (mBeanServer == null && createServer) {
185 mBeanServer = MBeanServerFactory.createMBeanServer();
186 serverCreated.set(true);
187 }
188 if (mBeanServer == null) {
189 throw new InitialisationException(ManagementMessages.cannotLocateOrCreateServer(), this);
190 }
191 if (connectorServerUrl != null) {
192 try {
193 JMXServiceURL url = new JMXServiceURL(connectorServerUrl);
194 if (connectorServerProperties == null)
195 {
196 connectorServerProperties = new HashMap(DEFAULT_CONNECTOR_SERVER_PROPERTIES);
197 }
198
199 if (!credentials.isEmpty())
200 {
201 JMXAuthenticator jmxAuthenticator = (JMXAuthenticator) ClassUtils.instanciateClass(
202 DEFAULT_JMX_AUTHENTICATOR, ClassUtils.NO_ARGS);
203
204 ((SimplePasswordJmxAuthenticator) jmxAuthenticator).setCredentials(credentials);
205 connectorServerProperties.put(JMXConnectorServer.AUTHENTICATOR, jmxAuthenticator);
206 }
207 connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, connectorServerProperties, mBeanServer);
208 } catch (Exception e) {
209 throw new InitialisationException(CoreMessages.failedToCreate("Jmx Connector"), e, this);
210 }
211 }
212
213
214 ManagerNotificationListener l = new ManagerNotificationListener() {
215 public void onNotification(UMOServerNotification notification)
216 {
217 if (notification.getAction() == ManagerNotification.MANAGER_STARTED_MODELS) {
218 try {
219 registerWrapperService();
220 registerStatisticsService();
221 registerMuleService();
222 registerConfigurationService();
223 registerModelServices();
224 registerComponentServices();
225 registerEndpointServices();
226 registerConnectorServices();
227 } catch (Exception e) {
228 throw new MuleRuntimeException(CoreMessages.objectFailedToInitialise("MBeans"), e);
229 }
230 }
231 }
232 };
233
234 try
235 {
236 UMOManager manager = MuleManager.getInstance();
237
238
239 if (StringUtils.isBlank(manager.getId()))
240 {
241
242 throw new IllegalArgumentException(
243 "Manager ID is mandatory when running with JmxAgent. Give your Mule configuration a valid ID.");
244 }
245 MuleManager.getInstance().registerListener(l);
246 } catch (NotificationException e) {
247 throw new InitialisationException(e, this);
248 }
249 initialized.compareAndSet(false, true);
250 }
251
252
253
254
255
256
257 public void start() throws UMOException
258 {
259 if (connectorServer != null) {
260 try {
261 logger.info("Starting JMX agent connector Server");
262 connectorServer.start();
263 } catch (Exception e) {
264 throw new JmxManagementException(CoreMessages.failedToStart("Jmx Connector"), e);
265 }
266 }
267 }
268
269
270
271
272
273
274 public void stop() throws UMOException
275 {
276 if (connectorServer != null) {
277 try {
278 connectorServer.stop();
279 } catch (Exception e) {
280 throw new JmxManagementException(CoreMessages.failedToStop("Jmx Connector"), e);
281 }
282 }
283 }
284
285
286
287
288
289
290 public void dispose()
291 {
292 if (mBeanServer != null) {
293 for (Iterator iterator = registeredMBeans.iterator(); iterator.hasNext();) {
294 ObjectName objectName = (ObjectName) iterator.next();
295 try {
296 mBeanServer.unregisterMBean(objectName);
297 } catch (Exception e) {
298 logger.warn("Failed to unregister MBean: " + objectName + ". Error is: " + e.getMessage());
299 }
300 }
301 if (serverCreated.get()) {
302 MBeanServerFactory.releaseMBeanServer(mBeanServer);
303 }
304 mBeanServer = null;
305 }
306
307 initialized.set(false);
308 }
309
310
311
312
313
314
315 public void registered()
316 {
317
318 }
319
320
321
322
323
324
325 public void unregistered()
326 {
327
328 }
329
330
331
332
333
334 protected void registerWrapperService() throws UMOException
335 {
336
337 final WrapperManagerAgent wmAgent = new WrapperManagerAgent();
338 final UMOManager manager = MuleManager.getInstance();
339 if (manager.lookupAgent(wmAgent.getName()) == null)
340 {
341 manager.registerAgent(wmAgent);
342 }
343 }
344
345
346 protected void registerStatisticsService() throws NotCompliantMBeanException, MBeanRegistrationException,
347 InstanceAlreadyExistsException, MalformedObjectNameException
348 {
349 ObjectName on = jmxSupport.getObjectName(jmxSupport.getDomainName() + ":type=org.mule.Statistics,name=AllStatistics");
350 StatisticsService mBean = new StatisticsService();
351 mBean.setManager(MuleManager.getInstance());
352 mBean.setEnabled(isEnableStatistics());
353 logger.debug("Registering statistics with name: " + on);
354 mBeanServer.registerMBean(mBean, on);
355 registeredMBeans.add(on);
356 }
357
358 protected void registerModelServices() throws NotCompliantMBeanException, MBeanRegistrationException,
359 InstanceAlreadyExistsException, MalformedObjectNameException
360 {
361 for (Iterator iterator = MuleManager.getInstance().getModels().values().iterator(); iterator.hasNext();)
362 {
363 UMOModel model = (UMOModel) iterator.next();
364 ModelServiceMBean serviceMBean = new ModelService(model);
365 String rawName = serviceMBean.getName() + "(" + serviceMBean.getType() + ")";
366 String name = jmxSupport.escape(rawName);
367 ObjectName on = jmxSupport.getObjectName(jmxSupport.getDomainName() + ":type=org.mule.Model,name=" + name);
368 logger.debug("Registering model with name: " + on);
369 mBeanServer.registerMBean(serviceMBean, on);
370 registeredMBeans.add(on);
371 }
372 }
373
374 protected void registerMuleService() throws NotCompliantMBeanException, MBeanRegistrationException,
375 InstanceAlreadyExistsException, MalformedObjectNameException
376 {
377 ObjectName on = jmxSupport.getObjectName(jmxSupport.getDomainName() + ":type=org.mule.ManagementContext,name=MuleServerInfo");
378 MuleServiceMBean serviceMBean = new MuleService();
379 logger.debug("Registering mule with name: " + on);
380 mBeanServer.registerMBean(serviceMBean, on);
381 registeredMBeans.add(on);
382 }
383
384 protected void registerConfigurationService() throws NotCompliantMBeanException, MBeanRegistrationException,
385 InstanceAlreadyExistsException, MalformedObjectNameException
386 {
387 ObjectName on = jmxSupport.getObjectName(jmxSupport.getDomainName() + ":type=org.mule.Configuration,name=GlobalConfiguration");
388 MuleConfigurationServiceMBean serviceMBean = new MuleConfigurationService();
389 logger.debug("Registering configuration with name: " + on);
390 mBeanServer.registerMBean(serviceMBean, on);
391 registeredMBeans.add(on);
392 }
393
394 protected void registerComponentServices() throws NotCompliantMBeanException, MBeanRegistrationException,
395 InstanceAlreadyExistsException, MalformedObjectNameException
396 {
397 for (Iterator iterator = MuleManager.getInstance().getModels().values().iterator(); iterator.hasNext();)
398 {
399 UMOModel model = (UMOModel) iterator.next();
400 Iterator iter = model.getComponentNames();
401
402 String rawName;
403 while (iter.hasNext()) {
404 rawName = iter.next().toString();
405 final String name = jmxSupport.escape(rawName);
406 ObjectName on = jmxSupport.getObjectName(jmxSupport.getDomainName() + ":type=org.mule.Component,name=" + name);
407 ComponentServiceMBean serviceMBean = new ComponentService(rawName);
408 logger.debug("Registering component with name: " + on);
409 mBeanServer.registerMBean(serviceMBean, on);
410 registeredMBeans.add(on);
411 }
412 }
413
414 }
415
416 protected void registerEndpointServices() throws NotCompliantMBeanException, MBeanRegistrationException,
417 InstanceAlreadyExistsException, MalformedObjectNameException
418 {
419 Iterator iter = MuleManager.getInstance().getConnectors().values().iterator();
420 UMOConnector connector;
421 while (iter.hasNext()) {
422 connector = (UMOConnector) iter.next();
423 if (connector instanceof AbstractConnector) {
424 for (Iterator iterator = ((AbstractConnector) connector).getReceivers().values().iterator(); iterator.hasNext();) {
425 EndpointServiceMBean mBean = new EndpointService((UMOMessageReceiver) iterator.next());
426 final String rawName = mBean.getName();
427 final String name = jmxSupport.escape(rawName);
428 if (logger.isInfoEnabled()) {
429 logger.info("Attempting to register service with name: " + jmxSupport.getDomainName()
430 + ":type=org.mule.umo.UMOEndpoint,name=" + name);
431 }
432 ObjectName on = jmxSupport.getObjectName(
433 jmxSupport.getDomainName() +
434 ":type=org.mule.Endpoint,component=" +
435 jmxSupport.escape(mBean.getComponentName()) +
436 ",name=" + name);
437 mBeanServer.registerMBean(mBean, on);
438 registeredMBeans.add(on);
439 logger.info("Registered Endpoint Service with name: " + on);
440 }
441 } else {
442 logger.warn("Connector: " + connector
443 + " is not an istance of AbstractConnector, cannot obtain Endpoint MBeans from it");
444 }
445
446 }
447 }
448
449 protected void registerConnectorServices() throws
450 MalformedObjectNameException,
451 NotCompliantMBeanException,
452 MBeanRegistrationException,
453 InstanceAlreadyExistsException
454 {
455 Iterator iter = MuleManager.getInstance().getConnectors().values().iterator();
456 while (iter.hasNext()) {
457 UMOConnector connector = (UMOConnector) iter.next();
458 ConnectorServiceMBean mBean = new ConnectorService(connector);
459 final String rawName = mBean.getName();
460 final String name = jmxSupport.escape(rawName);
461 final String stringName = jmxSupport.getDomainName() + ":type=org.mule.Connector,name=" + name;
462 if (logger.isDebugEnabled()) {
463 logger.debug("Attempting to register service with name: " + stringName);
464 }
465 ObjectName oName = jmxSupport.getObjectName(stringName);
466 mBeanServer.registerMBean(mBean, oName);
467 registeredMBeans.add(oName);
468 logger.info("Registered Connector Service with name " + oName);
469 }
470 }
471
472
473
474
475 public boolean isCreateServer()
476 {
477 return createServer;
478 }
479
480
481
482
483 public void setCreateServer(boolean createServer)
484 {
485 this.createServer = createServer;
486 }
487
488
489
490
491 public boolean isLocateServer()
492 {
493 return locateServer;
494 }
495
496
497
498
499 public void setLocateServer(boolean locateServer)
500 {
501 this.locateServer = locateServer;
502 }
503
504
505
506
507 public String getConnectorServerUrl()
508 {
509 return connectorServerUrl;
510 }
511
512
513
514
515 public void setConnectorServerUrl(String connectorServerUrl)
516 {
517 this.connectorServerUrl = connectorServerUrl;
518 }
519
520
521
522
523 public boolean isEnableStatistics()
524 {
525 return enableStatistics;
526 }
527
528
529
530
531 public void setEnableStatistics(boolean enableStatistics)
532 {
533 this.enableStatistics = enableStatistics;
534 }
535
536
537
538
539 public MBeanServer getMBeanServer()
540 {
541 return mBeanServer;
542 }
543
544
545
546
547 public void setMBeanServer(MBeanServer mBeanServer)
548 {
549 this.mBeanServer = mBeanServer;
550 }
551
552
553
554
555
556
557 public Map getConnectorServerProperties() {
558 return connectorServerProperties;
559 }
560
561
562
563
564
565
566
567
568
569 public void setConnectorServerProperties(Map connectorServerProperties) {
570 this.connectorServerProperties = connectorServerProperties;
571 }
572
573
574
575
576
577
578
579 public JmxSupportFactory getJmxSupportFactory()
580 {
581 return jmxSupportFactory;
582 }
583
584
585
586
587
588
589 public void setJmxSupportFactory(JmxSupportFactory jmxSupportFactory)
590 {
591 this.jmxSupportFactory = jmxSupportFactory;
592 }
593
594
595
596
597
598
599
600 public void setCredentials(final Map newCredentials)
601 {
602 this.credentials.clear();
603 if (newCredentials != null && !newCredentials.isEmpty())
604 {
605 this.credentials.putAll(newCredentials);
606 }
607 }
608 }