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

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit a2384804c527c64290cfae1fa988f1f394890e91
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Jul 24 17:51:24 2024 +0100

    Add JreCompat support for Subject.callAs()
    
    With the changes coming in Java 23 we need to move away from
    Subject.doAs() but the replacement isn't available in Java 17. Hence use
    JreCompat.
---
 .../org/apache/tomcat/util/compat/Jre18Compat.java | 71 ++++++++++++++++++++++
 .../org/apache/tomcat/util/compat/Jre19Compat.java |  2 +-
 java/org/apache/tomcat/util/compat/JreCompat.java  | 39 ++++++++++++
 .../tomcat/util/compat/LocalStrings.properties     |  1 +
 4 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/tomcat/util/compat/Jre18Compat.java 
b/java/org/apache/tomcat/util/compat/Jre18Compat.java
new file mode 100644
index 0000000000..b83999f179
--- /dev/null
+++ b/java/org/apache/tomcat/util/compat/Jre18Compat.java
@@ -0,0 +1,71 @@
+/*
+ *  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.tomcat.util.compat;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionException;
+
+import javax.security.auth.Subject;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
+
+public class Jre18Compat extends JreCompat {
+
+    private static final Log log = LogFactory.getLog(Jre18Compat.class);
+    private static final StringManager sm = 
StringManager.getManager(Jre18Compat.class);
+
+    private static final Method callAsMethod;
+
+    static {
+        Method m1 = null;
+
+        try {
+            m1 = Subject.class.getMethod("classAS", Subject.class, 
Callable.class);
+        } catch (NoSuchMethodException e) {
+            // Must before-Java 18
+            log.debug(sm.getString("jre18Compat.javaPre18"), e);
+        }
+
+        callAsMethod = m1;
+    }
+
+
+    static boolean isSupported() {
+        return callAsMethod != null;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T callAs(Subject subject, Callable<T> action) throws 
CompletionException {
+        try {
+            return (T) callAsMethod.invoke(null, subject, action);
+        } catch (IllegalAccessException e) {
+            throw new CompletionException(e);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof CompletionException) {
+                throw (CompletionException) cause;
+            }
+            throw new CompletionException(e);
+        }
+    }
+}
diff --git a/java/org/apache/tomcat/util/compat/Jre19Compat.java 
b/java/org/apache/tomcat/util/compat/Jre19Compat.java
index 60ee0c2dc1..fd9b85c515 100644
--- a/java/org/apache/tomcat/util/compat/Jre19Compat.java
+++ b/java/org/apache/tomcat/util/compat/Jre19Compat.java
@@ -22,7 +22,7 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
 
-public class Jre19Compat extends JreCompat {
+public class Jre19Compat extends Jre18Compat {
 
     private static final Log log = LogFactory.getLog(Jre19Compat.class);
     private static final StringManager sm = 
StringManager.getManager(Jre19Compat.class);
diff --git a/java/org/apache/tomcat/util/compat/JreCompat.java 
b/java/org/apache/tomcat/util/compat/JreCompat.java
index 743f76e64f..9227c2deac 100644
--- a/java/org/apache/tomcat/util/compat/JreCompat.java
+++ b/java/org/apache/tomcat/util/compat/JreCompat.java
@@ -17,6 +17,11 @@
 package org.apache.tomcat.util.compat;
 
 import java.lang.reflect.Field;
+import java.security.PrivilegedExceptionAction;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionException;
+
+import javax.security.auth.Subject;
 
 import org.apache.tomcat.util.res.StringManager;
 
@@ -29,6 +34,7 @@ public class JreCompat {
 
     private static final JreCompat instance;
     private static final boolean graalAvailable;
+    private static final boolean jre18Available;
     private static final boolean jre19Available;
     private static final boolean jre21Available;
     private static final boolean jre22Available;
@@ -53,21 +59,31 @@ public class JreCompat {
             jre22Available = true;
             jre21Available = true;
             jre19Available = true;
+            jre18Available = true;
         } else if (Jre21Compat.isSupported()) {
             instance = new Jre21Compat();
             jre22Available = false;
             jre21Available = true;
             jre19Available = true;
+            jre18Available = true;
         } else if (Jre19Compat.isSupported()) {
             instance = new Jre19Compat();
             jre22Available = false;
             jre21Available = false;
             jre19Available = true;
+            jre18Available = true;
+        } else if (Jre18Compat.isSupported()) {
+            instance = new Jre19Compat();
+            jre22Available = false;
+            jre21Available = false;
+            jre19Available = false;
+            jre18Available = true;
         } else {
             instance = new JreCompat();
             jre22Available = false;
             jre21Available = false;
             jre19Available = false;
+            jre18Available = false;
         }
     }
 
@@ -82,6 +98,11 @@ public class JreCompat {
     }
 
 
+    public static boolean isJre18Available() {
+        return jre18Available;
+    }
+
+
     public static boolean isJre19Available() {
         return jre19Available;
     }
@@ -97,6 +118,24 @@ public class JreCompat {
     }
 
 
+    // Java 17 implementations of Java 18 methods
+
+    @SuppressWarnings("removal")
+    public <T> T callAs(Subject subject, Callable<T> action) throws 
CompletionException {
+        try {
+            return Subject.doAs(subject, new PrivilegedExceptionAction<T>() {
+
+                @Override
+                public T run() throws Exception {
+                    return action.call();
+                }
+            });
+        } catch (Exception e) {
+            throw new CompletionException(e);
+        }
+    }
+
+
     // Java 17 implementations of Java 19 methods
 
     /**
diff --git a/java/org/apache/tomcat/util/compat/LocalStrings.properties 
b/java/org/apache/tomcat/util/compat/LocalStrings.properties
index e3bbf2b43b..40184d95ab 100644
--- a/java/org/apache/tomcat/util/compat/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/compat/LocalStrings.properties
@@ -13,5 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+jre18Compat.javaPre18=Method not found so assuming code is running on a 
pre-Java 18 JVM
 jre22Compat.javaPre22=Class not found so assuming code is running on a 
pre-Java 22 JVM
 jre22Compat.unexpected=Failed to create references to Java 22 classes and 
methods


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to