View Javadoc
1   package com.atlassian.sal.core.executor;
2   
3   import com.atlassian.sal.api.executor.ThreadLocalContextManager;
4   
5   import java.util.concurrent.Callable;
6   
7   import static com.google.common.base.Preconditions.checkNotNull;
8   
9   /**
10   * A wrapping callable that copies the thread local state into the calling code
11   *
12   * @since 2.0
13   */
14  class ThreadLocalDelegateCallable<C, T> implements Callable<T> {
15      private final Callable<T> delegate;
16      private final ThreadLocalContextManager<C> manager;
17      private final C context;
18      private final ClassLoader contextClassLoader;
19  
20      /**
21       * Create a new callable
22       *
23       * @param manager  The context manager to get the context from
24       * @param delegate The callable to delegate to
25       */
26      ThreadLocalDelegateCallable(ThreadLocalContextManager<C> manager, Callable<T> delegate) {
27          this.delegate = checkNotNull(delegate);
28          this.manager = checkNotNull(manager);
29          this.context = manager.getThreadLocalContext();
30          this.contextClassLoader = Thread.currentThread().getContextClassLoader();
31      }
32  
33      public T call() throws Exception {
34          ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
35          try {
36              Thread.currentThread().setContextClassLoader(contextClassLoader);
37              manager.setThreadLocalContext(context);
38              return delegate.call();
39          } finally {
40              Thread.currentThread().setContextClassLoader(oldContextClassLoader);
41              manager.clearThreadLocalContext();
42          }
43      }
44  }