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 6795092946a5e3ce6a14d04b432dcdf909df776a Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Oct 10 13:09:51 2024 -0600 Remove JreCompat for Java < 21 --- .../authenticator/SpnegoAuthenticator.java | 7 +- .../org/apache/tomcat/util/compat/Jre19Compat.java | 84 ------------ .../org/apache/tomcat/util/compat/Jre21Compat.java | 107 --------------- .../org/apache/tomcat/util/compat/Jre22Compat.java | 2 +- java/org/apache/tomcat/util/compat/JreCompat.java | 150 +-------------------- .../tomcat/util/compat/LocalStrings.properties | 2 - .../tomcat/util/compat/LocalStrings_fr.properties | 3 - .../tomcat/util/compat/LocalStrings_ja.properties | 3 - .../tomcat/util/threads/VirtualThreadExecutor.java | 9 +- 9 files changed, 9 insertions(+), 358 deletions(-) diff --git a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java index 9227238198..496c5c1c87 100644 --- a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java +++ b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java @@ -36,7 +36,6 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; -import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.compat.JreVendor; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; @@ -208,13 +207,13 @@ public class SpnegoAuthenticator extends AuthenticatorBase { } else { credentialLifetime = GSSCredential.DEFAULT_LIFETIME; } - gssContext = manager.createContext(JreCompat.getInstance().callAs(subject, () -> { + gssContext = manager.createContext(Subject.callAs(subject, () -> { return manager.createCredential(null, credentialLifetime, new Oid("1.3.6.1.5.5.2"), GSSCredential.ACCEPT_ONLY); })); final GSSContext gssContextFinal = gssContext; - outToken = JreCompat.getInstance().callAs(subject, () -> { + outToken = Subject.callAs(subject, () -> { return gssContextFinal.acceptSecContext(decoded, 0, decoded.length); }); @@ -228,7 +227,7 @@ public class SpnegoAuthenticator extends AuthenticatorBase { return false; } - principal = JreCompat.getInstance().callAs(subject, () -> { + principal = Subject.callAs(subject, () -> { return context.getRealm().authenticate(gssContextFinal, storeDelegatedCredential); }); } catch (GSSException e) { diff --git a/java/org/apache/tomcat/util/compat/Jre19Compat.java b/java/org/apache/tomcat/util/compat/Jre19Compat.java deleted file mode 100644 index 60ee0c2dc1..0000000000 --- a/java/org/apache/tomcat/util/compat/Jre19Compat.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.Field; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.util.res.StringManager; - -public class Jre19Compat extends JreCompat { - - private static final Log log = LogFactory.getLog(Jre19Compat.class); - private static final StringManager sm = StringManager.getManager(Jre19Compat.class); - - private static final boolean supported; - - static { - // Don't need any Java 19 specific classes (yet) so just test for one of - // the new ones for now. - Class<?> c1 = null; - try { - c1 = Class.forName("java.lang.WrongThreadException"); - } catch (ClassNotFoundException cnfe) { - // Must be pre-Java 19 - log.debug(sm.getString("jre19Compat.javaPre19"), cnfe); - } - - supported = (c1 != null); - } - - static boolean isSupported() { - return supported; - } - - @Override - public Object getExecutor(Thread thread) - throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - - Object result = super.getExecutor(thread); - - if (result == null) { - Object holder = null; - Object task = null; - try { - Field holderField = thread.getClass().getDeclaredField("holder"); - holderField.setAccessible(true); - holder = holderField.get(thread); - - Field taskField = holder.getClass().getDeclaredField("task"); - taskField.setAccessible(true); - task = taskField.get(holder); - } catch (NoSuchFieldException nfe) { - return null; - } - - if (task!= null && task.getClass().getCanonicalName() != null && - (task.getClass().getCanonicalName().equals( - "org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") || - task.getClass().getCanonicalName().equals( - "java.util.concurrent.ThreadPoolExecutor.Worker"))) { - Field executorField = task.getClass().getDeclaredField("this$0"); - executorField.setAccessible(true); - result = executorField.get(task); - } - } - - return result; - } -} diff --git a/java/org/apache/tomcat/util/compat/Jre21Compat.java b/java/org/apache/tomcat/util/compat/Jre21Compat.java deleted file mode 100644 index c534ea4e2d..0000000000 --- a/java/org/apache/tomcat/util/compat/Jre21Compat.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 Jre21Compat extends Jre19Compat { - - private static final Log log = LogFactory.getLog(Jre21Compat.class); - private static final StringManager sm = StringManager.getManager(Jre21Compat.class); - - private static final Method nameMethod; - private static final Method startMethod; - private static final Method ofVirtualMethod; - private static final Method callAsMethod; - - - static { - Class<?> c1 = null; - Method m1 = null; - Method m2 = null; - Method m3 = null; - Method m4 = null; - - try { - c1 = Class.forName("java.lang.Thread$Builder"); - m1 = c1.getMethod("name", String.class, long.class); - m2 = c1.getMethod("start", Runnable.class); - m3 = Thread.class.getMethod("ofVirtual", (Class<?>[]) null); - m4 = Subject.class.getMethod("callAs", Subject.class, Callable.class); - } catch (ClassNotFoundException e) { - // Must be pre-Java 21 - log.debug(sm.getString("jre21Compat.javaPre21"), e); - } catch (ReflectiveOperationException e) { - // Should never happen - log.error(sm.getString("jre21Compat.unexpected"), e); - } - nameMethod = m1; - startMethod = m2; - ofVirtualMethod = m3; - callAsMethod = m4; - } - - static boolean isSupported() { - return ofVirtualMethod != null; - } - - @Override - public Object createVirtualThreadBuilder(String name) { - try { - Object threadBuilder = ofVirtualMethod.invoke(null, (Object[]) null); - nameMethod.invoke(threadBuilder, name, Long.valueOf(0)); - return threadBuilder; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new UnsupportedOperationException(e); - } - } - - @Override - public void threadBuilderStart(Object threadBuilder, Runnable command) { - try { - startMethod.invoke(threadBuilder, command); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new UnsupportedOperationException(e); - } - } - - - @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/Jre22Compat.java b/java/org/apache/tomcat/util/compat/Jre22Compat.java index fd45c20bd6..97566f51a4 100644 --- a/java/org/apache/tomcat/util/compat/Jre22Compat.java +++ b/java/org/apache/tomcat/util/compat/Jre22Compat.java @@ -20,7 +20,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.res.StringManager; -public class Jre22Compat extends Jre21Compat { +public class Jre22Compat extends JreCompat { private static final Log log = LogFactory.getLog(Jre22Compat.class); private static final StringManager sm = StringManager.getManager(Jre22Compat.class); diff --git a/java/org/apache/tomcat/util/compat/JreCompat.java b/java/org/apache/tomcat/util/compat/JreCompat.java index 8f05646535..6fe6254e04 100644 --- a/java/org/apache/tomcat/util/compat/JreCompat.java +++ b/java/org/apache/tomcat/util/compat/JreCompat.java @@ -16,27 +16,15 @@ */ 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; - /** - * This is the base implementation class for JRE compatibility and provides an implementation based on Java 17. + * This is the base implementation class for JRE compatibility and provides an implementation based on Java 21. * Sub-classes may extend this class and provide alternative implementations for later JRE versions */ public class JreCompat { private static final JreCompat instance; private static final boolean graalAvailable; - private static final boolean jre19Available; - private static final boolean jre21Available; private static final boolean jre22Available; - private static final StringManager sm = StringManager.getManager(JreCompat.class); static { boolean result = false; @@ -50,28 +38,14 @@ public class JreCompat { } graalAvailable = result || System.getProperty("org.graalvm.nativeimage.imagecode") != null; - // This is Tomcat 12.0.x with a minimum Java version of Java 17. + // This is Tomcat 12.0.x with a minimum Java version of Java 21. // Look for the highest supported JVM first if (Jre22Compat.isSupported()) { instance = new Jre22Compat(); jre22Available = true; - jre21Available = true; - jre19Available = true; - } else if (Jre21Compat.isSupported()) { - instance = new Jre21Compat(); - jre22Available = false; - jre21Available = true; - jre19Available = true; - } else if (Jre19Compat.isSupported()) { - instance = new Jre19Compat(); - jre22Available = false; - jre21Available = false; - jre19Available = true; } else { instance = new JreCompat(); jre22Available = false; - jre21Available = false; - jre19Available = false; } } @@ -86,127 +60,7 @@ public class JreCompat { } - public static boolean isJre19Available() { - return jre19Available; - } - - - public static boolean isJre21Available() { - return jre21Available; - } - - public static boolean isJre22Available() { return jre22Available; } - - - // Java 17 implementations of Java 19 methods - - /** - * Obtains the executor, if any, used to create the provided thread. - * - * @param thread The thread to examine - * - * @return The executor, if any, that created the provided thread - * - * @throws NoSuchFieldException If a field used via reflection to obtain the executor cannot be found - * @throws SecurityException If a security exception occurs while trying to identify the executor - * @throws IllegalArgumentException If the instance object does not match the class of the field when obtaining a - * field value via reflection - * @throws IllegalAccessException If a field is not accessible due to access restrictions - */ - public Object getExecutor(Thread thread) - throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - - Object result = null; - - // Runnable wrapped by Thread - // "target" in Sun/Oracle JDK - // "runnable" in IBM JDK - // "action" in Apache Harmony - Object target = null; - for (String fieldName : new String[] { "target", "runnable", "action" }) { - try { - Field targetField = thread.getClass().getDeclaredField(fieldName); - targetField.setAccessible(true); - target = targetField.get(thread); - break; - } catch (NoSuchFieldException nfe) { - continue; - } - } - - // "java.util.concurrent" code is in public domain, - // so all implementations are similar including our - // internal fork. - if (target != null && target.getClass().getCanonicalName() != null && (target.getClass().getCanonicalName() - .equals("org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") || - target.getClass().getCanonicalName().equals("java.util.concurrent.ThreadPoolExecutor.Worker"))) { - Field executorField = target.getClass().getDeclaredField("this$0"); - executorField.setAccessible(true); - result = executorField.get(target); - } - - return result; - } - - - // Java 17 implementations of Java 21 methods - - /** - * Create a thread builder for virtual threads using the given name to name the threads. - * - * @param name The base name for the threads - * - * @return The thread buidler for virtual threads - */ - public Object createVirtualThreadBuilder(String name) { - throw new UnsupportedOperationException(sm.getString("jreCompat.noVirtualThreads")); - } - - - /** - * Create a thread with the given thread builder and use it to execute the given runnable. - * - * @param threadBuilder The thread builder to use to create a thread - * @param command The command to run - */ - public void threadBuilderStart(Object threadBuilder, Runnable command) { - throw new UnsupportedOperationException(sm.getString("jreCompat.noVirtualThreads")); - } - - - /* - * This is a slightly different usage of JreCompat. - * - * Subject.doAs() was deprecated in Java 18 and replaced with Subject.callAs(). As of Java 23, calling - * Subject.doAs() will trigger an UnsupportedOperationException unless the java.security.manager system property is - * set. To avoid Tomcat installations using Spnego authentication having to set this value, JreCompat is used to - * call Subject.callAs() instead. - * - * Because Java versions 18 to 22 inclusive support both the old and the new method, the switch over can occur at - * any Java version from 18 to 22 inclusive. Java 21 onwards was selected as it as an LTS version and that removes - * the need to add a Jre18Compat class. - * - * So, the slightly longer description for this method is: - * - * Java 17 implementation of a method replaced between Java 18 and 22 with the replacement method being used by - * Tomcat when running on Java 21 onwards. - */ - - @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); - } - } } diff --git a/java/org/apache/tomcat/util/compat/LocalStrings.properties b/java/org/apache/tomcat/util/compat/LocalStrings.properties index 40184d95ab..0df209897e 100644 --- a/java/org/apache/tomcat/util/compat/LocalStrings.properties +++ b/java/org/apache/tomcat/util/compat/LocalStrings.properties @@ -13,6 +13,4 @@ # 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 diff --git a/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties b/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties index 959fefa499..6051bcc9b1 100644 --- a/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties +++ b/java/org/apache/tomcat/util/compat/LocalStrings_fr.properties @@ -16,7 +16,4 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations -jre18Compat.javaPre18=Le code est considéré être exécuté sur une JVM antérieure à Java 18 car la méthode n'a pas été trouvée - jre22Compat.javaPre22=Le code est considéré être exécuté sur une JVM antérieure à Java 22 car la classe n'a pas été trouvée -jre22Compat.unexpected=Impossible de créer les références vers les classes et méthodes de Java 22 diff --git a/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties b/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties index 8649df4bf1..4129aabc83 100644 --- a/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties +++ b/java/org/apache/tomcat/util/compat/LocalStrings_ja.properties @@ -16,7 +16,4 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations -jre18Compat.javaPre18=メソッドが見つからないため、Java 18 以前の JVM で実行されていると仮定します - jre22Compat.javaPre22=クラスが見つからないため、コードが Java 22 以前の JVM で実行されていると仮定します -jre22Compat.unexpected=Java 22のクラストメソッドへの参照を作成するのに失敗しました diff --git a/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java b/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java index 54453a9a66..8f6b4f64d6 100644 --- a/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java +++ b/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java @@ -23,7 +23,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; -import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.res.StringManager; /** @@ -35,12 +34,10 @@ public class VirtualThreadExecutor extends AbstractExecutorService { private CountDownLatch shutdown = new CountDownLatch(1); - private final JreCompat jreCompat = JreCompat.getInstance(); - - private Object threadBuilder; + private Thread.Builder threadBuilder; public VirtualThreadExecutor(String namePrefix) { - threadBuilder = jreCompat.createVirtualThreadBuilder(namePrefix); + threadBuilder = Thread.ofVirtual().name(namePrefix, 0); } @Override @@ -49,7 +46,7 @@ public class VirtualThreadExecutor extends AbstractExecutorService { throw new RejectedExecutionException( sm.getString("virtualThreadExecutor.taskRejected", command.toString(), this.toString())); } - jreCompat.threadBuilderStart(threadBuilder, command); + threadBuilder.start(command); } @Override --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org