This is an automated email from the ASF dual-hosted git repository. rzo1 pushed a commit to branch 7935 in repository https://gitbox.apache.org/repos/asf/storm.git
commit 5ad245a29704bc11ecd37e255abce839591266d4 Author: Richard Zowalla <[email protected]> AuthorDate: Sun Feb 23 17:00:50 2025 +0100 #7935 - Use reflection to handle Java SecurityManager deprecation --- .github/workflows/maven.yaml | 2 +- .../org/apache/storm/security/auth/ReqContext.java | 76 ++++++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index 1bb4e1afe..643442841 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -28,7 +28,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest ] - java: [ 17, 21 ] + java: [ 17, 21, 24 ] module: [ Client, Server, Core, External, Check-Updated-License-Files, Integration-Test ] experimental: [false] fail-fast: false 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..c591f9632 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.currect() 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); + } + } + }
