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

View File

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