View Javadoc
1   package com.atlassian.plugin.util;
2   
3   import java.util.concurrent.Callable;
4   
5   import static java.util.concurrent.Executors.callable;
6   
7   /**
8    * Utility to run Runnable implementations in a different ClassLoader.
9    *
10   * @since 2.5.0
11   */
12  public class ContextClassLoaderSwitchingUtil {
13      /**
14       * Executes the provided {@link Runnable} implementation in the specified {@link ClassLoader}.
15       * <p>
16       * Utilises the {@link com.atlassian.plugin.util.ClassLoaderStack#push} method to save the old {@link ClassLoader} and
17       * set the one specified as <code>newClassLoader</code>. {@link com.atlassian.plugin.util.ClassLoaderStack#pop} is
18       * called in a finally block to ensure the {@link ClassLoader} is set back to the original one.
19       *
20       * @param newClassLoader The {@link ClassLoader} to run the specified {@link Runnable} in.
21       * @param runnable       The implementation to be run in the specified {@link ClassLoader}
22       */
23      public static void runInContext(ClassLoader newClassLoader, Runnable runnable) {
24          try {
25              runInContext(newClassLoader, callable(runnable));
26          } catch (RuntimeException re) {
27              throw re;
28          } catch (Exception e) {
29              // Do nothing, this can't happen
30          }
31      }
32  
33      /**
34       * Executes the provided {@link Callable} implementation in the specified {@link ClassLoader}.
35       * <p>
36       * Utilises the {@link com.atlassian.plugin.util.ClassLoaderStack#push} method to save the old {@link ClassLoader} and
37       * set the one specified as <code>newClassLoader</code>. {@link com.atlassian.plugin.util.ClassLoaderStack#pop} is
38       * called in a finally block to ensure the {@link ClassLoader} is set back to the original one.
39       *
40       * @param newClassLoader The {@link ClassLoader} to run the specified {@link Runnable} in.
41       * @param callable       The implementation to be run in the specified {@link ClassLoader}
42       * @return the result of the {@link Callable}
43       * @since 2.7.0
44       */
45      public static <T> T runInContext(ClassLoader newClassLoader, Callable<T> callable) throws Exception {
46          ClassLoaderStack.push(newClassLoader);
47          try {
48              return callable.call();
49          } finally {
50              ClassLoaderStack.pop();
51          }
52      }
53  }