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 /**
15 * Executes the provided {@link Runnable} implementation in the specified {@link ClassLoader}.
16 * <p/>
17 * Utilises the {@link com.atlassian.plugin.util.ClassLoaderStack#push} method to save the old {@link ClassLoader} and
18 * set the one specified as <code>newClassLoader</code>. {@link com.atlassian.plugin.util.ClassLoaderStack#pop} is
19 * called in a finally block to ensure the {@link ClassLoader} is set back to the original one.
20 *
21 * @param newClassLoader The {@link ClassLoader} to run the specified {@link Runnable} in.
22 * @param runnable The implementation to be run in the specified {@link ClassLoader}
23 */
24 public static void runInContext(ClassLoader newClassLoader, Runnable runnable)
25 {
26 try
27 {
28 runInContext(newClassLoader, callable(runnable));
29 }
30 catch (RuntimeException re)
31 {
32 throw re;
33 }
34 catch (Exception e)
35 {
36 // Do nothing, this can't happen
37 }
38 }
39
40 /**
41 * Executes the provided {@link Callable} implementation in the specified {@link ClassLoader}.
42 * <p/>
43 * Utilises the {@link com.atlassian.plugin.util.ClassLoaderStack#push} method to save the old {@link ClassLoader} and
44 * set the one specified as <code>newClassLoader</code>. {@link com.atlassian.plugin.util.ClassLoaderStack#pop} is
45 * called in a finally block to ensure the {@link ClassLoader} is set back to the original one.
46 *
47 * @param newClassLoader The {@link ClassLoader} to run the specified {@link Runnable} in.
48 * @param callable The implementation to be run in the specified {@link ClassLoader}
49 * @return the result of the {@link Callable}
50 * @since 2.7.0
51 */
52 public static <T> T runInContext(ClassLoader newClassLoader, Callable<T> callable) throws Exception
53 {
54 ClassLoaderStack.push(newClassLoader);
55 try
56 {
57 return callable.call();
58 }
59 finally
60 {
61 ClassLoaderStack.pop();
62 }
63 }
64 }