com.atlassian.bamboo.specs.maven.sandbox.SecureMethodInvoker Maven / Gradle / Ivy
package com.atlassian.bamboo.specs.maven.sandbox;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
public final class SecureMethodInvoker {
public static class SecureMethodInvocationException extends RuntimeException {
public SecureMethodInvocationException(final Exception e) {
super(e);
}
}
private SecureMethodInvoker() {
}
public static void startPerThreadSecurity(
final Map specializedVerifiers,
final ThreadPermissionVerifier defaultPermissionVerifier) {
BambooSpecsSecurityManager.setPermissionCheckers(specializedVerifiers, defaultPermissionVerifier);
}
public static void endPerThreadSecurity() {
BambooSpecsSecurityManager.clearPermissionCheckers();
}
public static T invoke(final Supplier hostileCode) {
return invokeInternal(hostileCode);
}
private static T invokeInternal(final Supplier hostileCode) {
final AtomicReference exceptionRef = new AtomicReference<>();
final AtomicReference errorRef = new AtomicReference<>();
final AtomicReference result = new AtomicReference<>();
final Runnable runnable = () -> {
try {
System.setSecurityManager(new BambooSpecsSecurityManager());
result.set(hostileCode.get());
} catch (final RuntimeException e) {
exceptionRef.set(e);
} catch (final Error e) {
errorRef.set(e);
} catch (final Exception e) {
exceptionRef.set(new SecureMethodInvocationException(e));
}
};
final SecurityManager prevSecurityManager = System.getSecurityManager();
try {
final Thread thread = new Thread(runnable);
thread.setName("Low privilege runner");
thread.start();
thread.join();
System.setSecurityManager(prevSecurityManager);
} catch (final InterruptedException ignored) {
//we got interrupted, oh well
}
throwIfNonEmpty(exceptionRef, errorRef);
return result.get();
}
private static void throwIfNonEmpty(final AtomicReference exceptionRef, final AtomicReference errorRef) {
final RuntimeException exception = exceptionRef.get();
if (exception != null) {
throw exception;
}
final Error error = errorRef.get();
if (error != null) {
throw error;
}
}
}