Вот многопоточное решение проблемы:
https://svn.code.sf.net/p/loggifier/code/trunk/de.unkrig.commons.lang/src/de/unkrig/commons/lang/security/Sandbox.java
<code>package de.unkrig.commons.lang.security;
import java.security.AccessControlContext;
import java.security.Permission;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import de.unkrig.commons.nullanalysis.Nullable;
/**
* This class establishes a security manager that confines the permissions for code executed through specific classes,
* which may be specified by class, class name and/or class loader.
* <p>
* To 'execute through a class' means that the execution stack includes the class. E.g., if a method of class {@code A}
* invokes a method of class {@code B}, which then invokes a method of class {@code C}, and all three classes were
* previously {@link #confine(Class, Permissions) confined}, then for all actions that are executed by class {@code C}
* the <i>intersection</i> of the three {@link Permissions} apply.
* <p>
* Once the permissions for a class, class name or class loader are confined, they cannot be changed; this prevents any
* attempts (e.g. of the confined class itself) to release the confinement.
* <p>
* Code example:
* <pre>
* Runnable unprivileged = new Runnable() {
* public void run() {
* System.getProperty("user.dir");
* }
* };
*
* // Run without confinement.
* unprivileged.run(); // Works fine.
*
* // Set the most strict permissions.
* Sandbox.confine(unprivileged.getClass(), new Permissions());
* unprivileged.run(); // Throws a SecurityException.
*
* // Attempt to change the permissions.
* {
* Permissions permissions = new Permissions();
* permissions.add(new AllPermission());
* Sandbox.confine(unprivileged.getClass(), permissions); // Throws a SecurityException.
* }
* unprivileged.run();
*
* /
публичный финал
песочница класса {
личная песочница () {}
приватная статическая финальная карта , AccessControlContext>
CHECKED_CLASSES = Collections.synchronizedMap (новый WeakHashMap , AccessControlContext> ());
частная статическая конечная карта
CHECKED_CLASS_NAMES = Collections.synchronizedMap (new HashMap ());
приватная статическая финальная карта
CHECKED_CLASS_LOADERS = Collections.synchronizedMap (new WeakHashMap ());
static {
// Установить наш собственный менеджер безопасности.
if (System.getSecurityManager ()! = null) {
бросить новый ExceptionInInitializerError («Менеджер безопасности уже настроен»);
}
System.setSecurityManager (new SecurityManager () {
@ Overide public void
checkPermission (@Nullable Permission perm) {
утверждать Пермь! = ноль;
for (Class <?> clasS: this.getClassContext ()) {
// Проверяем, был ли установлен ACC для класса.
{
AccessControlContext acc = Sandbox.CHECKED_CLASSES.get (clasS);
if (acc! = null) acc.checkPermission (perm);
}
// Проверяем, был ли установлен ACC для имени класса.
{
AccessControlContext acc = Sandbox.CHECKED_CLASS_NAMES.get (clasS.getName ());
if (acc! = null) acc.checkPermission (perm);
}
// Проверяем, был ли установлен ACC для загрузчика классов.
{
AccessControlContext acc = Sandbox.CHECKED_CLASS_LOADERS.get (clasS.getClassLoader ());
if (acc! = null) acc.checkPermission (perm);
}
}
}
});
}
// --------------------------
/ **
* Все будущие действия, которые выполняются с помощью {@code clasS}, будут проверены на соответствие с {@code
* accessControlContext}.
*
* @throws SecurityException Разрешения уже ограничены для {@code clasS}
* /
публичная статическая пустота
ограничение (класс <?> clasS, AccessControlContext accessControlContext) {
if (Sandbox.CHECKED_CLASSES.containsKey (clasS)) {
выбросить новое SecurityException («Попытка изменить контекст управления доступом для« + clasS + »);
}
Sandbox.CHECKED_CLASSES.put (clasS, accessControlContext);
}
/ **
* Все будущие действия, которые выполняются с помощью {@code clasS}, будут проверены на соответствие с {@code
* protectionDomain}.
*
* @throws SecurityException Разрешения уже ограничены для {@code clasS}
* /
публичная статическая пустота
ограничение (класс <?> clasS, ProtectionDomain protectionDomain) {
Sandbox.confine (
учебный класс,
новый AccessControlContext (новый ProtectionDomain [] {protectionDomain})
);
}
/ **
* Все будущие действия, которые выполняются с помощью {@code clasS}, будут проверены на соответствие с {@code
* разрешения}.
*
* @throws SecurityException Разрешения уже ограничены для {@code clasS}
* /
публичная статическая пустота
ограничение (класс <?> clasS, права доступа) {
Sandbox.confine (clasS, новый ProtectionDomain (ноль, разрешения));
}
// Код для CHECKED_CLASS_NAMES и CHECKED_CLASS_LOADERS здесь опущен.
}
Прокомментируйте, пожалуйста!
CU
Arno