View Javadoc

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