NIFI-12072 moved to StackWalker API elimnating usage of SecurityManager (#7742)

This commit is contained in:
Joe Witt 2023-09-16 14:05:22 -07:00 committed by GitHub
parent cb03d6de74
commit cbf5bb98f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 22 additions and 31 deletions

View File

@ -54,15 +54,16 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.Optional;
/**
* THREAD SAFE
*/
public class NarThreadContextClassLoader extends URLClassLoader {
static final ContextSecurityManager contextSecurityManager = new ContextSecurityManager();
private final ClassLoader forward = ClassLoader.getSystemClassLoader();
private static final List<Class<?>> narSpecificClasses = new ArrayList<>();
@ -135,29 +136,27 @@ public class NarThreadContextClassLoader extends URLClassLoader {
}
private ClassLoader lookupClassLoader() {
final Class<?>[] classStack = contextSecurityManager.getExecutionStack();
// When new Threads are created, the new Thread inherits the ClassLoaderContext of
// the caller. However, the call stack of that new Thread may not trace back to any NiFi-specific
// code. Therefore, the NarThreadContextClassLoader will be unable to find the appropriate NAR
// ClassLoader. As a result, we want to set the ContextClassLoader to the NAR ClassLoader that
// contains the class or resource that we are looking for.
// This locks the current Thread into the appropriate NAR ClassLoader Context. The framework will change
// the ContextClassLoader back to the NarThreadContextClassLoader as appropriate via the
// {@link FlowEngine.beforeExecute(Thread, Runnable)} and
// {@link FlowEngine.afterExecute(Thread, Runnable)} methods.
for (Class<?> currentClass : classStack) {
final Class<?> narClass = findNarClass(currentClass);
if (narClass != null) {
final ClassLoader desiredClassLoader = narClass.getClassLoader();
// When new Threads are created, the new Thread inherits the ClassLoaderContext of
// the caller. However, the call stack of that new Thread may not trace back to any NiFi-specific
// code. Therefore, the NarThreadContextClassLoader will be unable to find the appropriate NAR
// ClassLoader. As a result, we want to set the ContextClassLoader to the NAR ClassLoader that
// contains the class or resource that we are looking for.
// This locks the current Thread into the appropriate NAR ClassLoader Context. The framework will change
// the ContextClassLoader back to the NarThreadContextClassLoader as appropriate via the
// {@link FlowEngine.beforeExecute(Thread, Runnable)} and
// {@link FlowEngine.afterExecute(Thread, Runnable)} methods.
if (desiredClassLoader instanceof NarClassLoader) {
Thread.currentThread().setContextClassLoader(desiredClassLoader);
}
return desiredClassLoader;
}
}
return forward;
final StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
final Optional<ClassLoader> callerClassLoader = walker.walk(s ->
s.map(StackWalker.StackFrame::getDeclaringClass)
.map(this::findNarClass)
.filter(Objects::nonNull)
.map(Class::getClassLoader)
.map(cl->cl instanceof NarClassLoader ? cl : null)
.filter(Objects::nonNull)
.findFirst());
callerClassLoader.ifPresent(Thread.currentThread()::setContextClassLoader);
return callerClassLoader.orElse(forward);
}
private Class<?> findNarClass(final Class<?> cls) {
@ -181,14 +180,6 @@ public class NarThreadContextClassLoader extends URLClassLoader {
return SingletonHolder.instance;
}
static class ContextSecurityManager extends SecurityManager {
Class<?>[] getExecutionStack() {
return getClassContext();
}
}
/**
* Constructs an instance of the given type using either default no args
* constructor or a constructor which takes a NiFiProperties object