View Javadoc

1   /*
2    * $Id: Mx4jAgent.java 11517 2008-03-31 21:34:19Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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  
11  package org.mule.module.management.agent;
12  
13  import org.mule.AbstractAgent;
14  import org.mule.api.MuleException;
15  import org.mule.api.lifecycle.InitialisationException;
16  import org.mule.config.MuleManifest;
17  import org.mule.config.i18n.CoreMessages;
18  import org.mule.config.i18n.MessageFactory;
19  import org.mule.module.management.mbean.MBeanServerFactory;
20  import org.mule.module.management.support.AutoDiscoveryJmxSupportFactory;
21  import org.mule.module.management.support.JmxSupport;
22  import org.mule.module.management.support.JmxSupportFactory;
23  import org.mule.module.xml.util.XMLUtils;
24  import org.mule.util.BeanUtils;
25  import org.mule.util.ClassUtils;
26  import org.mule.util.StringUtils;
27  import org.mule.util.SystemUtils;
28  
29  import java.net.URI;
30  import java.util.HashMap;
31  import java.util.Map;
32  
33  import javax.management.InstanceNotFoundException;
34  import javax.management.MBeanException;
35  import javax.management.MBeanRegistrationException;
36  import javax.management.MBeanServer;
37  import javax.management.MalformedObjectNameException;
38  import javax.management.ObjectName;
39  import javax.management.ReflectionException;
40  import javax.xml.transform.TransformerFactoryConfigurationError;
41  
42  import mx4j.log.CommonsLogger;
43  import mx4j.log.Log;
44  import mx4j.tools.adaptor.http.HttpAdaptor;
45  import mx4j.tools.adaptor.http.XSLTProcessor;
46  import mx4j.tools.adaptor.ssl.SSLAdaptorServerSocketFactory;
47  import mx4j.tools.adaptor.ssl.SSLAdaptorServerSocketFactoryMBean;
48  
49  import org.apache.commons.logging.LogFactory;
50  
51  /**
52   * <code>Mx4jAgent</code> configures an Mx4J Http Adaptor for Jmx management,
53   * statistics and configuration viewing of a Mule instance.
54   * <p/>
55   * TODO MULE-1353
56   */
57  public class Mx4jAgent extends AbstractAgent
58  {
59      public static final String HTTP_ADAPTER_OBJECT_NAME = "name=Mx4jHttpAdapter";
60  
61      protected static final String DEFAULT_PATH_IN_JAR = StringUtils.replaceChars(ClassUtils.getPackageName(Mx4jAgent.class), '.', '/') +
62                                                          "/http/xsl";
63  
64      private static final org.apache.commons.logging.Log logger = LogFactory.getLog(Mx4jAgent.class);
65  
66      private static final String PROTOCOL_PREFIX = "http://";
67      public static final String DEFAULT_HOSTNAME = "localhost";
68      public static final int DEFAULT_PORT = 9999;
69      public static final String DEFAULT_JMX_ADAPTOR_URL = PROTOCOL_PREFIX + DEFAULT_HOSTNAME + ":" + DEFAULT_PORT;
70  
71      private String jmxAdaptorUrl;
72      private String host;
73      private String port;
74  
75      private HttpAdaptor adaptor;
76      private MBeanServer mBeanServer;
77      private ObjectName adaptorName;
78  
79      // Adaptor overrides
80      private String login;
81  
82      private String password;
83  
84      private String authenticationMethod = "basic";
85  
86      // TODO AH check how an embedded scenario can be handled (no mule home) 
87      private String xslFilePath = System.getProperty("mule.home") + "/lib/mule/mule-module-management-" +
88              MuleManifest.getProductVersion() + ".jar";
89  
90      private String pathInJar = DEFAULT_PATH_IN_JAR;
91  
92      private boolean cacheXsl = true;
93  
94      // SSL/TLS socket factory config
95      private Map socketFactoryProperties = new HashMap();
96  
97      private JmxSupportFactory jmxSupportFactory = AutoDiscoveryJmxSupportFactory.getInstance();
98      private JmxSupport jmxSupport;
99  
100 
101     public Mx4jAgent()
102     {
103         super("jmx-mx4j-adaptor");
104     }
105 
106     protected HttpAdaptor createAdaptor() throws Exception
107     {
108 
109         Log.redirectTo(new CommonsLogger());
110         URI uri = new URI(StringUtils.stripToEmpty(jmxAdaptorUrl));
111         adaptor = new HttpAdaptor(uri.getPort(), uri.getHost());
112 
113         // Set the XSLT Processor with any local overrides
114         XSLTProcessor processor;
115         try
116         {
117             processor = new XSLTProcessor();
118         }
119         catch (TransformerFactoryConfigurationError e)
120         {
121             System.setProperty("javax.xml.transform.TransformerFactory", XMLUtils.TRANSFORMER_FACTORY_JDK5);
122             processor = new XSLTProcessor();
123         }
124 
125         if (StringUtils.isNotBlank(xslFilePath))
126         {
127             processor.setFile(xslFilePath.trim());
128         }
129 
130         if (StringUtils.isNotBlank(pathInJar))
131         {
132             processor.setPathInJar(pathInJar.trim());
133         }
134 
135         processor.setUseCache(cacheXsl);
136 
137         adaptor.setProcessor(processor);
138 
139         // Set endpoint authentication if required
140         if (login != null)
141         {
142             adaptor.addAuthorization(login, password);
143             adaptor.setAuthenticationMethod(authenticationMethod);
144         }
145 
146         if (socketFactoryProperties != null && !socketFactoryProperties.isEmpty())
147         {
148             SSLAdaptorServerSocketFactoryMBean factory;
149             if (SystemUtils.isIbmJDK())
150             {
151                 factory = new IBMSslAdapterServerSocketFactory();
152             }
153             else
154             {
155                 // BEA are using Sun's JSSE, so no extra checks necessary
156                 factory = new SSLAdaptorServerSocketFactory();
157             }
158             BeanUtils.populateWithoutFail(factory, socketFactoryProperties, true);
159             adaptor.setSocketFactory(factory);
160         }
161 
162         return adaptor;
163     }
164 
165     public void initialise() throws InitialisationException
166     {
167         try
168         {
169             jmxSupport = jmxSupportFactory.getJmxSupport();
170             mBeanServer = MBeanServerFactory.getOrCreateMBeanServer();
171 
172             if (StringUtils.isBlank(jmxAdaptorUrl))
173             {
174                 if (StringUtils.isNotBlank(host) && StringUtils.isNotBlank(port))
175                 {
176                     jmxAdaptorUrl = PROTOCOL_PREFIX + host + ":" + port;
177                 }
178                 else
179                 {
180                     jmxAdaptorUrl = DEFAULT_JMX_ADAPTOR_URL;
181                 }
182             }
183 
184             adaptor = createAdaptor();
185             adaptorName = jmxSupport.getObjectName(jmxSupport.getDomainName(muleContext) + ":" + HTTP_ADAPTER_OBJECT_NAME);
186 
187             unregisterMBeansIfNecessary();
188             mBeanServer.registerMBean(adaptor, adaptorName);
189         }
190         catch (Exception e)
191         {
192             throw new InitialisationException(CoreMessages.failedToStart("mx4j agent"), e, this);
193         }
194     }
195 
196     public void start() throws MuleException
197     {
198         if (mBeanServer == null)
199         {
200             throw new InitialisationException(MessageFactory.createStaticMessage("mBeanServer has not yet been created"), this);
201         }
202         
203         try
204         {
205             mBeanServer.invoke(adaptorName, "start", null, null);
206         }
207         catch (InstanceNotFoundException e)
208         {
209             throw new JmxManagementException(
210                 CoreMessages.failedToStart("Mx4j agent"), adaptorName, e);
211         }
212         catch (MBeanException e)
213         {
214             throw new JmxManagementException(
215                 CoreMessages.failedToStart("Mx4j agent"), adaptorName, e);
216         }
217         catch (ReflectionException e)
218         {
219             // ignore
220         }
221     }
222 
223     public void stop() throws MuleException
224     {
225         if (mBeanServer == null)
226         {
227             return;
228         }
229         try
230         {
231             mBeanServer.invoke(adaptorName, "stop", null, null);
232         }
233         catch (InstanceNotFoundException e)
234         {
235             throw new JmxManagementException(
236                 CoreMessages.failedToStop("Mx4j agent"), adaptorName, e);
237         }
238         catch (MBeanException e)
239         {
240             throw new JmxManagementException(
241                 CoreMessages.failedToStop("Mx4j agent"), adaptorName, e);
242         }
243         catch (ReflectionException e)
244         {
245             // ignore
246         }
247     }
248 
249     /**
250      * Unregister all Mx4j MBeans if there are any left over the old deployment
251      */
252     protected void unregisterMBeansIfNecessary()
253         throws MalformedObjectNameException, InstanceNotFoundException, MBeanRegistrationException
254     {
255         if (mBeanServer != null && mBeanServer.isRegistered(adaptorName))
256         {
257             mBeanServer.unregisterMBean(adaptorName);
258         }
259     }
260 
261     /* @see org.mule.api.lifecycle.Disposable#dispose() */
262     public void dispose()
263     {
264         try
265         {
266             stop();
267         }
268         catch (Exception e)
269         {
270             logger.warn("Failed to stop Mx4jAgent: " + e.getMessage());
271         }
272         finally
273         {
274             try
275             {
276                 unregisterMBeansIfNecessary();
277             }
278             catch (Exception e)
279             {
280                 logger.error("Couldn't unregister MBean: "
281                              + (adaptorName != null ? adaptorName.getCanonicalName() : "null"), e);
282             }
283         }
284     }
285 
286     /* @see org.mule.api.context.Agent#registered() */
287     public void registered()
288     {
289         // nothing to do
290     }
291 
292     /* @see org.mule.api.context.Agent#unregistered() */
293     public void unregistered()
294     {
295         // nothing to do
296     }
297 
298     // /////////////////////////////////////////////////////////////////////////
299     // Getters and setters
300     // /////////////////////////////////////////////////////////////////////////
301 
302     /* @see org.mule.api.context.Agent#getDescription() */
303     public String getDescription()
304     {
305         return "MX4J Http adaptor: " + jmxAdaptorUrl;
306     }
307 
308     /** @return Returns the jmxAdaptorUrl. */
309     public String getJmxAdaptorUrl()
310     {
311         return jmxAdaptorUrl;
312     }
313 
314     /** @param jmxAdaptorUrl The jmxAdaptorUrl to set. */
315     public void setJmxAdaptorUrl(String jmxAdaptorUrl)
316     {
317         this.jmxAdaptorUrl = jmxAdaptorUrl;
318     }
319 
320     public Map getSocketFactoryProperties()
321     {
322         return socketFactoryProperties;
323     }
324 
325     public void setSocketFactoryProperties(Map socketFactoryProperties)
326     {
327         this.socketFactoryProperties = socketFactoryProperties;
328     }
329 
330     public String getLogin()
331     {
332         return login;
333     }
334 
335     public void setLogin(String login)
336     {
337         this.login = login;
338     }
339 
340     public String getPassword()
341     {
342         return password;
343     }
344 
345     public void setPassword(String password)
346     {
347         this.password = password;
348     }
349 
350     public String getAuthenticationMethod()
351     {
352         return authenticationMethod;
353     }
354 
355     public void setAuthenticationMethod(String authenticationMethod)
356     {
357         this.authenticationMethod = authenticationMethod;
358     }
359 
360     public String getXslFilePath()
361     {
362         return xslFilePath;
363     }
364 
365     public void setXslFilePath(String xslFilePath)
366     {
367         this.xslFilePath = xslFilePath;
368     }
369 
370     public String getPathInJar()
371     {
372         return pathInJar;
373     }
374 
375     public void setPathInJar(String pathInJar)
376     {
377         this.pathInJar = pathInJar;
378     }
379 
380     public boolean isCacheXsl()
381     {
382         return cacheXsl;
383     }
384 
385     public void setCacheXsl(boolean cacheXsl)
386     {
387         this.cacheXsl = cacheXsl;
388     }
389 
390 
391     public String getHost()
392     {
393         return host;
394     }
395 
396     public void setHost(String host)
397     {
398         this.host = host;
399     }
400 
401     public String getPort()
402     {
403         return port;
404     }
405 
406     public void setPort(String port)
407     {
408         this.port = port;
409     }
410 }