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

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

commit 93cd15715aa6df13460a01a4547aec625b01c5a3
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  | 41 +++++++++++++
 .../tomcat/util/compat/LocalStrings.properties     |  2 +
 4 files changed, 115 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..50c744b1d5
--- /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 Jre16Compat {
+
+    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 45ce68b666..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 Jre16Compat {
+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 0c1840c90b..c1bf67a815 100644
--- a/java/org/apache/tomcat/util/compat/JreCompat.java
+++ b/java/org/apache/tomcat/util/compat/JreCompat.java
@@ -27,11 +27,15 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
+import java.security.PrivilegedExceptionAction;
 import java.util.Deque;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionException;
 import java.util.jar.JarFile;
 
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLParameters;
+import javax.security.auth.Subject;
 
 import org.apache.tomcat.util.res.StringManager;
 
@@ -49,6 +53,7 @@ public class JreCompat {
     private static final boolean jre9Available;
     private static final boolean jre11Available;
     private static final boolean jre16Available;
+    private static final boolean jre18Available;
     private static final boolean jre19Available;
     private static final boolean jre21Available;
     private static final boolean jre22Available;
@@ -76,6 +81,7 @@ public class JreCompat {
             jre22Available = true;
             jre21Available = true;
             jre19Available = true;
+            jre18Available = true;
             jre16Available = true;
             jre9Available = true;
         } else if (Jre21Compat.isSupported()) {
@@ -83,6 +89,7 @@ public class JreCompat {
             jre22Available = false;
             jre21Available = true;
             jre19Available = true;
+            jre18Available = true;
             jre16Available = true;
             jre9Available = true;
         } else if (Jre19Compat.isSupported()) {
@@ -90,6 +97,15 @@ public class JreCompat {
             jre22Available = false;
             jre21Available = false;
             jre19Available = true;
+            jre18Available = true;
+            jre16Available = true;
+            jre9Available = true;
+        } else if (Jre18Compat.isSupported()) {
+            instance = new Jre19Compat();
+            jre22Available = false;
+            jre21Available = false;
+            jre19Available = false;
+            jre18Available = true;
             jre16Available = true;
             jre9Available = true;
         } else if (Jre16Compat.isSupported()) {
@@ -97,6 +113,7 @@ public class JreCompat {
             jre22Available = false;
             jre21Available = false;
             jre19Available = false;
+            jre18Available = false;
             jre16Available = true;
             jre9Available = true;
         } else if (Jre9Compat.isSupported()) {
@@ -104,6 +121,7 @@ public class JreCompat {
             jre22Available = false;
             jre21Available = false;
             jre19Available = false;
+            jre18Available = false;
             jre16Available = false;
             jre9Available = true;
         } else {
@@ -111,6 +129,7 @@ public class JreCompat {
             jre22Available = false;
             jre21Available = false;
             jre19Available = false;
+            jre18Available = false;
             jre16Available = false;
             jre9Available = false;
         }
@@ -159,6 +178,11 @@ public class JreCompat {
     }
 
 
+    public static boolean isJre18Available() {
+        return jre18Available;
+    }
+
+
     public static boolean isJre19Available() {
         return jre19Available;
     }
@@ -382,6 +406,23 @@ public class JreCompat {
     }
 
 
+    // Java 8 implementations of Java 18 methods
+
+    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 8 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 f9bbc23f24..bc12e98d3f 100644
--- a/java/org/apache/tomcat/util/compat/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/compat/LocalStrings.properties
@@ -16,6 +16,8 @@
 jre16Compat.javaPre16=Class not found so assuming code is running on a 
pre-Java 16 JVM
 jre16Compat.unexpected=Failed to create references to Java 16 classes and 
methods
 
+jre18Compat.javaPre18=Method not found so assuming code is running on a 
pre-Java 18 JVM
+
 jre19Compat.javaPre19=Class not found so assuming code is running on a 
pre-Java 19 JVM
 
 jre21Compat.javaPre21=Class not found so assuming code is running on a 
pre-Java 21 JVM


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

Reply via email to