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 javax.management.MBeanException;
10  import javax.management.MBeanRegistration;
11  import javax.management.MBeanServer;
12  import javax.management.NotCompliantMBeanException;
13  import javax.management.ObjectName;
14  import javax.management.ReflectionException;
15  import javax.management.StandardMBean;
16  
17  import org.apache.commons.logging.Log;
18  import org.apache.commons.logging.LogFactory;
19  
20  /**
21   * Ensures any external jmx invocation (like e.g. remote) is executed with a correct application
22   * classloader (otherwise a bootstrap classloader is used by default for platform mbean server). Note
23   * the irony - extends StandardMBean, but StandardMBean is not your 'standard mbean', but rather a
24   * special kind of the DynamicMBean which generates attributes/operations based on the passed in
25   * interface (via reflection).
26   */
27  public class ClassloaderSwitchingMBeanWrapper extends StandardMBean implements MBeanRegistration
28  {
29      protected Log logger = LogFactory.getLog(getClass());
30  
31      private ClassLoader executionClassLoader;
32  
33      public <T> ClassloaderSwitchingMBeanWrapper(T implementation, Class<T> mbeanInterface, ClassLoader executionClassLoader)
34              throws NotCompliantMBeanException
35      {
36          super(implementation, mbeanInterface);
37          this.executionClassLoader = executionClassLoader;
38      }
39  
40      @Override
41      public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException
42      {
43          ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
44          try
45          {
46              Thread.currentThread().setContextClassLoader(executionClassLoader);
47              return super.invoke(actionName, params, signature);
48          }
49          catch (MBeanException mbex)
50          {
51              throw mbex;
52          }
53          catch (ReflectionException rex)
54          {
55              throw rex;
56          }
57          catch (Exception ex)
58          {
59              logger.error(String.format("MBean operation '%s' failed", actionName), ex);
60              if (ex instanceof RuntimeException)
61              {
62                  throw (RuntimeException) ex;
63              }
64  
65              throw new RuntimeException(ex);
66          }
67          finally
68          {
69              Thread.currentThread().setContextClassLoader(oldCl);
70          }
71      }
72  
73      public ClassLoader getExecutionClassLoader()
74      {
75          return executionClassLoader;
76      }
77  
78      public void setExecutionClassLoader(ClassLoader executionClassLoader)
79      {
80          this.executionClassLoader = executionClassLoader;
81      }
82  
83      public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception
84      {
85          if (getImplementation() instanceof MBeanRegistration)
86          {
87              return ((MBeanRegistration) getImplementation()).preRegister(server, name);
88          }
89  
90          return name;
91      }
92  
93      public void postRegister(Boolean registrationDone)
94      {
95          if (getImplementation() instanceof MBeanRegistration)
96          {
97              ((MBeanRegistration) getImplementation()).postRegister(registrationDone);
98          }
99      }
100 
101     public void preDeregister() throws Exception
102     {
103         if (getImplementation() instanceof MBeanRegistration)
104         {
105             ((MBeanRegistration) getImplementation()).preDeregister();
106         }
107     }
108 
109     public void postDeregister()
110     {
111         if (getImplementation() instanceof MBeanRegistration)
112         {
113             ((MBeanRegistration) getImplementation()).postDeregister();
114         }
115     }
116 }