/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain. Use, modify, and
* redistribute this code in any way without acknowledgement.
*/
package java.util.concurrent;
import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* A {@link FutureTask} that executes, if allowed, with the current
* access control context and context class loader of the thread
* creating the task. A new PrivilegedFutureTask
* can be created within an {@link AccessController#doPrivileged}
* action to run tasks under the selected permission settings
* holding within that action.
* @see Executors
*
* @since 1.5
* @author Doug Lea
*/
public class PrivilegedFutureTask extends FutureTask {
private final ClassLoader ccl;
private final AccessControlContext acc;
/**
* Constructs a PrivilegedFutureTask that will, upon running,
* execute the given Callable under the current access control
* context, with the current context class loader as the context class
* loader.
*
* @throws AccessControlException if the current access control context
* does not have permission to both set and get context class loader.
*/
public PrivilegedFutureTask(Callable task) {
super(task);
this.ccl = Thread.currentThread().getContextClassLoader();
this.acc = AccessController.getContext();
acc.checkPermission(new RuntimePermission("getContextClassLoader"));
acc.checkPermission(new RuntimePermission("setContextClassLoader"));
}
/**
* Executes within the established access control and context
* class loader if possible, else causes invocations of {@link
* Future#get} to receive the associated AccessControlException.
*/
public void run() {
try {
AccessController.doPrivileged(new PrivilegedFutureAction(), acc);
} catch(Throwable ex) {
setException(ex);
}
}
private class PrivilegedFutureAction implements PrivilegedAction {
public Object run() {
ClassLoader saved = null;
try {
ClassLoader current = Thread.currentThread().getContextClassLoader();
if (ccl != current) {
Thread.currentThread().setContextClassLoader(ccl);
saved = current;
}
PrivilegedFutureTask.super.run();
return null;
} finally {
if (saved != null)
Thread.currentThread().setContextClassLoader(saved);
}
}
}
}