This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch jdk24
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit 8c2e610af1cd6e6f99610e5f10c45f9c28936831
Author: Richard Zowalla <r...@apache.org>
AuthorDate: Tue Jun 24 10:37:06 2025 +0200

    JDK 24 Support?
---
 .../core/security/AbstractSecurityService.java     | 31 +++++++-
 .../apache/openejb/core/security/PolicyJDK24.java  | 46 +++++++++++
 .../core/security/jacc/BasicJaccProvider.java      |  3 +-
 .../openejb/client/JaasIdentityResolver.java       |  5 +-
 .../apache/openejb/client/util/JDK24Subject.java   | 88 ++++++++++++++++++++++
 .../java/org/apache/openejb/client/MainTest.java   |  5 +-
 6 files changed, 169 insertions(+), 9 deletions(-)

diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
index cb56a5f9b7..b1bf205863 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
@@ -50,6 +50,7 @@ import java.security.Policy;
 import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -62,6 +63,8 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static java.util.Arrays.asList;
+import static org.apache.openejb.InterfaceType.BUSINESS_LOCALBEAN_HOME;
+import static org.apache.openejb.InterfaceType.LOCALBEAN;
 
 /**
  * This security service chooses a UUID as its token as this can be serialized
@@ -379,6 +382,7 @@ public abstract class AbstractSecurityService implements 
DestroyableResource, Se
             if ("LocalBean".equals(name) || "LocalBeanHome".equals(name)) {
                 name = null;
             }
+
             final Identity currentIdentity = clientIdentity.get();
             final SecurityContext securityContext;
             if (currentIdentity == null) {
@@ -422,11 +426,11 @@ public abstract class AbstractSecurityService implements 
DestroyableResource, Se
 
         // check the system provided provider first - if for some reason it 
isn't loaded, load it
         final String systemPolicyProvider = 
SystemInstance.get().getOptions().getProperties().getProperty("jakarta.security.jacc.policy.provider");
-        if (systemPolicyProvider != null && Policy.getPolicy() == null) {
+        if (systemPolicyProvider != null && getPolicy() == null) {
             installPolicy(systemPolicyProvider);
         }
 
-        if (! 
JaccProvider.Policy.class.getName().equals(Policy.getPolicy().getClass().getName()))
 {
+        if (! 
JaccProvider.Policy.class.getName().equals(getPolicy().getClass().getName())) {
             // this should delegate to the policy installed above
             installPolicy(JaccProvider.Policy.class.getName());
         }
@@ -436,15 +440,34 @@ public abstract class AbstractSecurityService implements 
DestroyableResource, Se
         try {
             final ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
             final Class policyClass = Class.forName(policyProvider, true, 
classLoader);
-            final Policy policy = (Policy) policyClass.newInstance();
+            final Policy policy = (Policy) 
policyClass.getDeclaredConstructor().newInstance();
             policy.refresh();
-            Policy.setPolicy(policy);
+            setPolicy(policy);
         } catch (final Exception e) {
             throw new IllegalStateException("Could not install JACC Policy 
Provider: " + policyProvider, e);
         }
     }
 
 
+    public static Policy getPolicy() {
+        Policy policy = PolicyJDK24.getPolicy();
+        if (policy == null) {
+            policy = Policy.getPolicy();
+        }
+
+        return policy;
+    }
+
+    public static void setPolicy(Policy policy) {
+        try {
+            Policy.setPolicy(policy);
+        } catch (UnsupportedOperationException e) {
+            //we are running JDK 24 or later, so no system-wide policy 
possible.
+            PolicyJDK24.setPolicy(policy);
+        }
+    }
+
+
     protected Subject createSubject(final String name, final String groupName) 
{
         if (name == null) {
             return null;
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/PolicyJDK24.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/PolicyJDK24.java
new file mode 100644
index 0000000000..6db9ccf4cb
--- /dev/null
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/PolicyJDK24.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.core.security;
+
+import java.security.Policy;
+
+/**
+ * A utility class to manage the Java Security Policy in a thread-safe manner.
+ * This class provides methods to get and set the security policy, ensuring
+ * that changes are synchronized across threads.
+ */
+public class PolicyJDK24 {
+
+    private static volatile Policy policy;
+
+    /**
+     * @return the policy
+     */
+    public static synchronized Policy getPolicy() {
+        return policy;
+    }
+
+    /**
+     * @param policy the policy to set
+     */
+    public static synchronized void setPolicy(Policy policy) {
+        PolicyJDK24.policy = policy;
+    }
+
+
+
+}
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
index 3db5c4af63..6a2f77811b 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
@@ -18,6 +18,7 @@
 package org.apache.openejb.core.security.jacc;
 
 import org.apache.openejb.core.security.JaccProvider;
+import org.apache.openejb.core.security.PolicyJDK24;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.spi.SecurityService;
 
@@ -66,7 +67,7 @@ public class BasicJaccProvider extends JaccProvider {
     private final java.security.Policy systemPolicy;
 
     public BasicJaccProvider() {
-        systemPolicy = Policy.getPolicy();
+        systemPolicy = PolicyJDK24.getPolicy();
     }
 
     public PolicyConfiguration getPolicyConfiguration(final String contextID, 
final boolean remove) throws PolicyContextException {
diff --git 
a/server/openejb-client/src/main/java/org/apache/openejb/client/JaasIdentityResolver.java
 
b/server/openejb-client/src/main/java/org/apache/openejb/client/JaasIdentityResolver.java
index 2193d03aaa..26fcf5cfd4 100644
--- 
a/server/openejb-client/src/main/java/org/apache/openejb/client/JaasIdentityResolver.java
+++ 
b/server/openejb-client/src/main/java/org/apache/openejb/client/JaasIdentityResolver.java
@@ -17,15 +17,16 @@
  */
 package org.apache.openejb.client;
 
+import org.apache.openejb.client.util.JDK24Subject;
+
 import javax.security.auth.Subject;
-import java.security.AccessController;
 import java.util.Set;
 
 public class JaasIdentityResolver implements IdentityResolver {
 
     @Override
     public Object getIdentity() {
-        final Subject subject = 
Subject.getSubject(AccessController.getContext());
+        final Subject subject = JDK24Subject.currentSubject();
         if (subject == null) {
             return null;
         }
diff --git 
a/server/openejb-client/src/main/java/org/apache/openejb/client/util/JDK24Subject.java
 
b/server/openejb-client/src/main/java/org/apache/openejb/client/util/JDK24Subject.java
new file mode 100644
index 0000000000..3b35ff8d87
--- /dev/null
+++ 
b/server/openejb-client/src/main/java/org/apache/openejb/client/util/JDK24Subject.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.client.util;
+
+import javax.security.auth.Subject;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class JDK24Subject {
+
+    private static final MethodHandle CURRENT = lookupCurrent();
+
+    /**
+     * 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);
+        }
+    }
+}
diff --git 
a/server/openejb-client/src/test/java/org/apache/openejb/client/MainTest.java 
b/server/openejb-client/src/test/java/org/apache/openejb/client/MainTest.java
index ea10f2e667..380407a481 100644
--- 
a/server/openejb-client/src/test/java/org/apache/openejb/client/MainTest.java
+++ 
b/server/openejb-client/src/test/java/org/apache/openejb/client/MainTest.java
@@ -18,6 +18,7 @@
 package org.apache.openejb.client;
 
 import junit.framework.TestCase;
+import org.apache.openejb.client.util.JDK24Subject;
 
 import javax.naming.Binding;
 import javax.naming.Context;
@@ -87,7 +88,7 @@ public class MainTest extends TestCase {
     public static class SecureMain {
 
         public static void main(String[] args) {
-            Subject subject = 
Subject.getSubject(AccessController.getContext());
+            Subject subject = JDK24Subject.currentSubject();
 
             // verify subject
             assertEquals("Should have one principal", 1, 
subject.getPrincipals().size());
@@ -109,7 +110,7 @@ public class MainTest extends TestCase {
     public static class NormalMain {
 
         public static void main(String[] args) {
-            Subject subject = 
Subject.getSubject(AccessController.getContext());
+            Subject subject = JDK24Subject.currentSubject();
 
             assertNull("subject is not null", subject);
 

Reply via email to