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 }