com.atlassian.bamboo.specs.maven.sandbox.ReflectionEnabledThreadPermissionVerifier Maven / Gradle / Ivy
package com.atlassian.bamboo.specs.maven.sandbox;
import java.io.File;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.ReflectPermission;
import java.security.Permission;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import static com.atlassian.bamboo.specs.maven.sandbox.StackTraceUtils.getCallerStack;
/**
* A permission checker allowing limted access to Reflection API.
*/
public final class ReflectionEnabledThreadPermissionVerifier extends AbstractThreadPermissionVerifier {
private final ClassLoader classLoader;
private final Set priorityClasspath;
ReflectionEnabledThreadPermissionVerifier(final ClassLoader classLoader, final Set priorityClasspath) {
this.classLoader = classLoader;
this.priorityClasspath = priorityClasspath;
}
@Override
public boolean checkPermissionFor(final Permission perm) {
final LowPrivilegeThreadPermissionVerifier lowPrivilegeThreadPermissionVerifier = new LowPrivilegeThreadPermissionVerifier(null, null);
if (lowPrivilegeThreadPermissionVerifier.checkPermissionFor(perm)) {
return true;
}
if (narrow(perm, ReflectPermission.class)
.map(ReflectPermission::getName)
.filter("suppressAccessChecks"::equals).isPresent()) {
final StackTraceElement[] callerStackTrace = Objects.requireNonNull(getCallerStack(AccessibleObject.class, Field.class));
final Set jarsOnStack = StackTraceUtils.getClassLocationsOnStack(classLoader, callerStackTrace);
return priorityClasspath.containsAll(jarsOnStack);
}
if (narrow(perm, RuntimePermission.class)
.map(RuntimePermission::getName)
.filter("accessDeclaredMembers"::equals).isPresent()) {
final StackTraceElement[] callerStackTrace = Objects.requireNonNull(getCallerStack(Class.class));
final Set jarsOnStack = StackTraceUtils.getClassLocationsOnStack(classLoader, callerStackTrace);
return priorityClasspath.containsAll(jarsOnStack);
}
return false;
}
private static Optional narrow(final S superclass, final Class runtimePermissionClass) {
return runtimePermissionClass.isInstance(superclass) ?
Optional.of(runtimePermissionClass.cast(superclass)) :
Optional.empty();
}
}