This is an automated email from the ASF dual-hosted git repository. rzo1 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/storm.git
The following commit(s) were added to refs/heads/master by this push: new 6240d6c80 #7935 - Use reflection to handle Java SecurityManager deprecation (#7971) 6240d6c80 is described below commit 6240d6c809c8086c265e08838620286470f0a900 Author: Richard Zowalla <13417392+r...@users.noreply.github.com> AuthorDate: Mon Mar 3 09:02:08 2025 +0100 #7935 - Use reflection to handle Java SecurityManager deprecation (#7971) * #7935 - Use reflection to handle Java SecurityManager deprecation --- .../org/apache/storm/security/auth/ReqContext.java | 76 ++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/storm-client/src/jvm/org/apache/storm/security/auth/ReqContext.java b/storm-client/src/jvm/org/apache/storm/security/auth/ReqContext.java index 11a1cdf2d..830165084 100644 --- a/storm-client/src/jvm/org/apache/storm/security/auth/ReqContext.java +++ b/storm-client/src/jvm/org/apache/storm/security/auth/ReqContext.java @@ -18,9 +18,10 @@ package org.apache.storm.security.auth; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.net.InetAddress; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.Principal; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @@ -36,10 +37,13 @@ import org.apache.storm.shade.com.google.common.annotations.VisibleForTesting; * </ol> */ public class ReqContext { + + private static final MethodHandle CURRENT = lookupCurrent(); + private static final AtomicInteger uniqueId = new AtomicInteger(0); //each thread will have its own request context private static final ThreadLocal<ReqContext> ctxt = - ThreadLocal.withInitial(() -> new ReqContext(AccessController.getContext())); + ThreadLocal.withInitial(ReqContext::new); private Subject subject; private InetAddress remoteAddr; private final int reqId; @@ -47,8 +51,8 @@ public class ReqContext { //private constructor @VisibleForTesting - public ReqContext(AccessControlContext aclCtxt) { - subject = Subject.getSubject(aclCtxt); + public ReqContext() { + subject = currentSubject(); reqId = uniqueId.incrementAndGet(); } @@ -161,4 +165,66 @@ public class ReqContext { public int requestID() { return reqId; } + + /** + * Maps to Subject.current() is available, otherwise maps to Subject.getSubject() + * @return the current subject + */ + public static Subject currentSubject() { + try { + return (Subject) CURRENT.invoke(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + private static MethodHandle lookupCurrent() { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + // Subject.getSubject(AccessControlContext) is deprecated for removal and replaced by + // Subject.current(). + // Lookup first the new API, since for Java versions where both exists, the + // new API delegates to the old API (for example Java 18, 19 and 20). + // Otherwise (Java 17), lookup the old API. + return lookup.findStatic(Subject.class, "current", + MethodType.methodType(Subject.class)); + } catch (NoSuchMethodException e) { + final MethodHandle getContext = lookupGetContext(); + final MethodHandle getSubject = lookupGetSubject(); + return MethodHandles.filterReturnValue(getContext, getSubject); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + } + + private static MethodHandle lookupGetSubject() { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + final Class<?> contextClazz = + ClassLoader.getSystemClassLoader() + .loadClass("java.security.AccessControlContext"); + return lookup.findStatic(Subject.class, "getSubject", + MethodType.methodType(Subject.class, contextClazz)); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) { + throw new AssertionError(e); + } + } + + private static MethodHandle lookupGetContext() { + try { + // Use reflection to work with Java versions that have and don't have AccessController. + final Class<?> controllerClazz = + ClassLoader.getSystemClassLoader().loadClass("java.security.AccessController"); + final Class<?> contextClazz = + ClassLoader.getSystemClassLoader() + .loadClass("java.security.AccessControlContext"); + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + return lookup.findStatic(controllerClazz, "getContext", + MethodType.methodType(contextClazz)); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) { + throw new AssertionError(e); + } + } + }