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

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


The following commit(s) were added to refs/heads/main by this push:
     new 4d20e86db3 Minor fixes from code review
4d20e86db3 is described below

commit 4d20e86db36bbab6148a4704a69914eaaa9fae64
Author: remm <[email protected]>
AuthorDate: Wed Jun 10 16:42:47 2026 +0200

    Minor fixes from code review
---
 .../catalina/ant/jmx/JMXAccessorConditionBase.java |  3 +-
 .../catalina/ant/jmx/JMXAccessorCreateTask.java    |  6 ++-
 .../ant/jmx/JMXAccessorEqualsCondition.java        |  1 -
 .../catalina/ant/jmx/JMXAccessorGetTask.java       |  4 +-
 .../catalina/ant/jmx/JMXAccessorInvokeTask.java    |  3 ++
 .../catalina/ant/jmx/JMXAccessorQueryTask.java     |  5 +-
 .../catalina/ant/jmx/JMXAccessorSetTask.java       |  4 +-
 .../apache/catalina/ant/jmx/JMXAccessorTask.java   | 25 +++++----
 .../ant/jmx/JMXAccessorUnregisterTask.java         |  8 +--
 .../catalina/authenticator/BasicAuthenticator.java |  6 ++-
 .../apache/catalina/authenticator/Constants.java   | 12 ++---
 .../authenticator/DigestAuthenticator.java         |  3 +-
 .../catalina/authenticator/SingleSignOnEntry.java  |  3 +-
 .../authenticator/SpnegoAuthenticator.java         |  2 +-
 .../jaspic/PersistentProviderRegistrations.java    |  7 +--
 .../jaspic/SimpleServerAuthContext.java            |  8 ++-
 .../apache/catalina/connector/CoyotePrincipal.java | 20 +++++++
 .../apache/catalina/connector/CoyoteReader.java    |  3 ++
 .../apache/catalina/connector/CoyoteWriter.java    |  1 -
 java/org/apache/catalina/connector/Request.java    |  5 +-
 java/org/apache/catalina/connector/Response.java   | 17 ++++--
 .../apache/catalina/connector/ResponseFacade.java  |  8 +--
 .../org/apache/catalina/core/AccessLogAdapter.java |  8 ++-
 .../apache/catalina/realm/GenericPrincipal.java    | 19 +++++++
 .../buildutil/translate/BackportTranslations.java  |  5 +-
 .../apache/tomcat/buildutil/translate/Import.java  |  1 +
 threadpool.patch                                   | 63 ++++++++++++++++++++++
 27 files changed, 195 insertions(+), 55 deletions(-)

diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
index e114f25439..7f64bbc81b 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
@@ -22,6 +22,7 @@ import java.net.MalformedURLException;
 import javax.management.MBeanServerConnection;
 import javax.management.ObjectName;
 
+import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.taskdefs.condition.Condition;
 
@@ -233,7 +234,7 @@ public abstract class JMXAccessorConditionBase extends 
ProjectComponent implemen
                 return result.toString();
             }
         } catch (Exception e) {
-            // ignore access or connection open errors
+            throw new BuildException("Cannot access JMX value for condition", 
e);
         }
         return null;
     }
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java
index be1fa8ee2f..18bc588615 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java
@@ -139,12 +139,14 @@ public class JMXAccessorCreateTask extends 
JMXAccessorTask {
 
     @Override
     public String jmxExecute(MBeanServerConnection jmxServerConnection) throws 
Exception {
-
         if (getName() == null) {
             throw new BuildException("Must specify a 'name'");
         }
         if ((className == null)) {
-            throw new BuildException("Must specify a 'className' for get");
+            throw new BuildException("Must specify a 'className' for create");
+        }
+        if (jmxServerConnection == null) {
+            throw new BuildException("Must open a connection!");
         }
         jmxCreate(jmxServerConnection, getName());
         return null;
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java
index a58fef60b4..b8d2c87ecc 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java
@@ -74,7 +74,6 @@ public class JMXAccessorEqualsCondition extends 
JMXAccessorConditionBase {
         if (getName() == null || getAttribute() == null) {
             throw new BuildException("Must specify an MBean name and attribute 
for equals condition");
         }
-        // FIXME check url or host/parameter
         String jmxValue = accessJMXValue();
         if (jmxValue != null) {
             return jmxValue.equals(value);
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java
index 4ad5b6c011..78fe5dfece 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java
@@ -89,13 +89,15 @@ public class JMXAccessorGetTask extends JMXAccessorTask {
 
     @Override
     public String jmxExecute(MBeanServerConnection jmxServerConnection) throws 
Exception {
-
         if (getName() == null) {
             throw new BuildException("Must specify a 'name'");
         }
         if ((attribute == null)) {
             throw new BuildException("Must specify a 'attribute' for get");
         }
+        if (jmxServerConnection == null) {
+            throw new BuildException("Must open a connection!");
+        }
         return jmxGet(jmxServerConnection, getName());
     }
 
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java
index 7fa478cb35..f1d0c50eb7 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java
@@ -156,6 +156,9 @@ public class JMXAccessorInvokeTask extends JMXAccessorTask {
         if ((operation == null)) {
             throw new BuildException("Must specify a 'operation' for call");
         }
+        if (jmxServerConnection == null) {
+            throw new BuildException("Must open a connection!");
+        }
         return jmxInvoke(jmxServerConnection, getName());
     }
 
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java
index 600f17751a..7e70bb7287 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java
@@ -90,12 +90,13 @@ public class JMXAccessorQueryTask extends JMXAccessorTask {
 
     @Override
     public String jmxExecute(MBeanServerConnection jmxServerConnection) throws 
Exception {
-
         if (getName() == null) {
             throw new BuildException("Must specify a 'name'");
         }
+        if (jmxServerConnection == null) {
+            throw new BuildException("Must open a connection!");
+        }
         return jmxQuery(jmxServerConnection, getName());
-
     }
 
 
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java
index 08fae8da40..b09de55dd7 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java
@@ -151,13 +151,15 @@ public class JMXAccessorSetTask extends JMXAccessorTask {
 
     @Override
     public String jmxExecute(MBeanServerConnection jmxServerConnection) throws 
Exception {
-
         if (getName() == null) {
             throw new BuildException("Must specify a 'name'");
         }
         if ((attribute == null || value == null)) {
             throw new BuildException("Must specify a 'attribute' and 'value' 
for set");
         }
+        if (jmxServerConnection == null) {
+            throw new BuildException("Must open a connection!");
+        }
         return jmxSet(jmxServerConnection, getName());
     }
 
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
index 8e27366a44..d9d2d1cd67 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
@@ -22,7 +22,6 @@ import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.UnknownHostException;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -436,6 +435,7 @@ public class JMXAccessorTask extends 
BaseRedirectorHelperTask {
             environment = new HashMap<>();
             environment.put(JMXConnector.CREDENTIALS, credentials);
         }
+        // FIXME: Referencing JMXConnector instead of MBeanServerConnection is 
needed to close the connection
         return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX), 
environment).getMBeanServerConnection();
 
     }
@@ -515,7 +515,6 @@ public class JMXAccessorTask extends 
BaseRedirectorHelperTask {
      * @return the JMX connection
      */
     protected MBeanServerConnection getJMXConnection() throws 
MalformedURLException, IOException {
-
         MBeanServerConnection jmxServerConnection = null;
         if (isUseRef()) {
             Object pref;
@@ -552,8 +551,7 @@ public class JMXAccessorTask extends 
BaseRedirectorHelperTask {
      * @exception Exception if an error occurs
      */
     public String jmxExecute(MBeanServerConnection jmxServerConnection) throws 
Exception {
-
-        if ((jmxServerConnection == null)) {
+        if (jmxServerConnection == null) {
             throw new BuildException("Must open a connection!");
         } else if (isEcho()) {
             handleOutput("JMX Connection ref=" + ref + " is open!");
@@ -562,7 +560,7 @@ public class JMXAccessorTask extends 
BaseRedirectorHelperTask {
     }
 
     /**
-     * Convert string to datatype FIXME How we can transfer values from ant 
project reference store (ref)?
+     * Convert string to datatype.
      *
      * @param value     The value
      * @param valueType The type
@@ -686,15 +684,16 @@ public class JMXAccessorTask extends 
BaseRedirectorHelperTask {
                 }
             }
         } else if (result instanceof TabularDataSupport data) {
-            for (Object key : data.keySet()) {
-                for (Object key1 : ((List<?>) key)) {
-                    CompositeData valuedata = data.get(new Object[] { key1 });
-                    Object value = valuedata.get("value");
-                    OpenType<?> type = 
valuedata.getCompositeType().getType("value");
-                    if (type instanceof SimpleType<?>) {
-                        setProperty(propertyPrefix + "." + key1, value);
+            for (Object rowObj : data.values()) {
+                CompositeData row = (CompositeData) rowObj;
+                CompositeType rowType = row.getCompositeType();
+                for (String fieldName : rowType.keySet()) {
+                    Object fieldValue = row.get(fieldName);
+                    OpenType<?> fieldType = rowType.getType(fieldName);
+                    if (fieldType instanceof SimpleType<?>) {
+                        setProperty(propertyPrefix + "." + fieldName, 
fieldValue);
                     } else {
-                        createProperty(propertyPrefix + "." + key1, value);
+                        createProperty(propertyPrefix + "." + fieldName, 
fieldValue);
                     }
                 }
             }
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java 
b/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java
index ed09b0fb09..ad7e47ac00 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java
@@ -59,11 +59,13 @@ public class JMXAccessorUnregisterTask extends 
JMXAccessorTask {
 
     @Override
     public String jmxExecute(MBeanServerConnection jmxServerConnection) throws 
Exception {
-
         if (getName() == null) {
             throw new BuildException("Must specify a 'name'");
         }
-        return jmxUuregister(jmxServerConnection, getName());
+        if (jmxServerConnection == null) {
+            throw new BuildException("Must open a connection!");
+        }
+        return jmxUnregister(jmxServerConnection, getName());
     }
 
 
@@ -77,7 +79,7 @@ public class JMXAccessorUnregisterTask extends 
JMXAccessorTask {
      *
      * @throws Exception An error occurred
      */
-    protected String jmxUuregister(MBeanServerConnection jmxServerConnection, 
String name) throws Exception {
+    protected String jmxUnregister(MBeanServerConnection jmxServerConnection, 
String name) throws Exception {
         if (isEcho()) {
             handleOutput("Unregister MBean " + name);
         }
diff --git a/java/org/apache/catalina/authenticator/BasicAuthenticator.java 
b/java/org/apache/catalina/authenticator/BasicAuthenticator.java
index 27f511ea30..68f915bb21 100644
--- a/java/org/apache/catalina/authenticator/BasicAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/BasicAuthenticator.java
@@ -50,7 +50,8 @@ public class BasicAuthenticator extends AuthenticatorBase {
 
 
     /**
-     * Returns the character set used for encoding credentials.
+     * Returns the character set used for encoding credentials, as set by the 
user.
+     * If the charset was null or empty, the effective charset will be 
ISO-8859-1.
      *
      * @return the character set name
      */
@@ -60,7 +61,8 @@ public class BasicAuthenticator extends AuthenticatorBase {
 
 
     /**
-     * Sets the character set used for encoding credentials.
+     * Sets the character set used for encoding credentials. Empty charsets 
will set
+     * ISO-8859-1.
      *
      * @param charsetString the character set name
      */
diff --git a/java/org/apache/catalina/authenticator/Constants.java 
b/java/org/apache/catalina/authenticator/Constants.java
index ecc11979c0..336baaa099 100644
--- a/java/org/apache/catalina/authenticator/Constants.java
+++ b/java/org/apache/catalina/authenticator/Constants.java
@@ -115,16 +115,16 @@ public class Constants {
 
 
     /**
-     * If the <code>cache</code> property of the authenticator is set, and the 
current request is part of a session, the
-     * password used to authenticate this user will be cached under this key 
to avoid the need for repeated calls to
-     * <code>Realm.authenticate()</code>.
+     * When the <code>cache</code> property of the authenticator is set to 
<code>false</code>, the Principal is not cached.
+     * In this case, if the current request is part of a session, the password 
used to authenticate this user will be stored
+     * under this key so the user can be re-authenticated on subsequent 
requests.
      */
     public static final String SESS_PASSWORD_NOTE = 
"org.apache.catalina.session.PASSWORD";
 
     /**
-     * If the <code>cache</code> property of the authenticator is set, and the 
current request is part of a session, the
-     * username used to authenticate this user will be cached under this key 
to avoid the need for repeated calls to
-     * <code>Realm.authenticate()</code>.
+     * When the <code>cache</code> property of the authenticator is set to 
<code>false</code>, the Principal is not cached.
+     * In this case, if the current request is part of a session, the username 
used to authenticate this user will be stored
+     * under this key so the user can be re-authenticated on subsequent 
requests.
      */
     public static final String SESS_USERNAME_NOTE = 
"org.apache.catalina.session.USERNAME";
 
diff --git a/java/org/apache/catalina/authenticator/DigestAuthenticator.java 
b/java/org/apache/catalina/authenticator/DigestAuthenticator.java
index a6c2cd9205..1189156b97 100644
--- a/java/org/apache/catalina/authenticator/DigestAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/DigestAuthenticator.java
@@ -665,8 +665,7 @@ public class DigestAuthenticator extends AuthenticatorBase {
             }
 
             // Validate the Realm name
-            String lcRealm = getRealmName(request.getContext());
-            if (!lcRealm.equals(realmName)) {
+            if (!realmName.equals(getRealmName(request.getContext()))) {
                 return false;
             }
 
diff --git a/java/org/apache/catalina/authenticator/SingleSignOnEntry.java 
b/java/org/apache/catalina/authenticator/SingleSignOnEntry.java
index ca82255023..5d233ac253 100644
--- a/java/org/apache/catalina/authenticator/SingleSignOnEntry.java
+++ b/java/org/apache/catalina/authenticator/SingleSignOnEntry.java
@@ -59,7 +59,8 @@ public class SingleSignOnEntry implements Serializable {
     private transient Principal principal = null;
 
     /**
-     * Map of session keys associated with this SSO entry.
+     * Set of session keys associated with this SSO entry. Backed by 
ConcurrentHashMap to take
+     * advantage of its thread safety features.
      */
     private final Map<SingleSignOnSessionKey,SingleSignOnSessionKey> 
sessionKeys = new ConcurrentHashMap<>();
 
diff --git a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java 
b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
index f7dd01a851..4a5a2236ba 100644
--- a/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java
@@ -327,7 +327,7 @@ public class SpnegoAuthenticator extends AuthenticatorBase {
             }
         }
 
-        // Send response token on success and failure
+        // Send response token since one is available, even for SC_UNAUTHORIZED
         response.setHeader(AUTH_HEADER_NAME,
                 AUTH_HEADER_VALUE_NEGOTIATE + " " + 
Base64.getEncoder().encodeToString(outToken));
 
diff --git 
a/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
 
b/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
index 0f5ba37615..98b510f608 100644
--- 
a/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
+++ 
b/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java
@@ -37,6 +37,7 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.digester.Digester;
 import org.apache.tomcat.util.res.StringManager;
+import org.apache.tomcat.util.security.Escape;
 import org.xml.sax.SAXException;
 
 /**
@@ -136,9 +137,9 @@ public final class PersistentProviderRegistrations {
                 writer.write(">\n");
                 for (Entry<String,String> entry : 
provider.getProperties().entrySet()) {
                     writer.write("    <property name=\"");
-                    writer.write(entry.getKey());
+                    writer.write(Escape.xml(entry.getKey()));
                     writer.write("\" value=\"");
-                    writer.write(entry.getValue());
+                    writer.write(Escape.xml(entry.getValue()));
                     writer.write("\"/>\n");
                 }
                 writer.write("  </provider>\n");
@@ -177,7 +178,7 @@ public final class PersistentProviderRegistrations {
     private static void writeOptional(String name, String value, Writer 
writer) throws IOException {
         if (value != null) {
             writer.write(" " + name + "=\"");
-            writer.write(value);
+            writer.write(Escape.xml(value));
             writer.write("\"");
         }
     }
diff --git 
a/java/org/apache/catalina/authenticator/jaspic/SimpleServerAuthContext.java 
b/java/org/apache/catalina/authenticator/jaspic/SimpleServerAuthContext.java
index 5aaaf27786..c87ec2950c 100644
--- a/java/org/apache/catalina/authenticator/jaspic/SimpleServerAuthContext.java
+++ b/java/org/apache/catalina/authenticator/jaspic/SimpleServerAuthContext.java
@@ -73,8 +73,12 @@ public class SimpleServerAuthContext implements 
ServerAuthContext {
      */
     @Override
     public AuthStatus secureResponse(MessageInfo messageInfo, Subject 
serviceSubject) throws AuthException {
-        ServerAuthModule module = modules.get(((Integer) 
messageInfo.getMap().get("moduleIndex")).intValue());
-        return module.secureResponse(messageInfo, serviceSubject);
+        if (messageInfo.getMap().get("moduleIndex") instanceof Integer 
moduleIndex) {
+            ServerAuthModule module = modules.get(moduleIndex.intValue());
+            return module.secureResponse(messageInfo, serviceSubject);
+        } else {
+            return AuthStatus.SEND_FAILURE;
+        }
     }
 
 
diff --git a/java/org/apache/catalina/connector/CoyotePrincipal.java 
b/java/org/apache/catalina/connector/CoyotePrincipal.java
index 32257536d6..35621823e2 100644
--- a/java/org/apache/catalina/connector/CoyotePrincipal.java
+++ b/java/org/apache/catalina/connector/CoyotePrincipal.java
@@ -19,6 +19,7 @@ package org.apache.catalina.connector;
 import java.io.Serial;
 import java.io.Serializable;
 import java.security.Principal;
+import java.util.Objects;
 
 /**
  * Generic implementation of <strong>java.security.Principal</strong> that is 
used to represent principals authenticated
@@ -70,4 +71,23 @@ public class CoyotePrincipal implements Principal, 
Serializable {
     }
 
 
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        CoyotePrincipal that = (CoyotePrincipal) obj;
+        return Objects.equals(this.name, that.name);
+    }
+
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+
+
 }
diff --git a/java/org/apache/catalina/connector/CoyoteReader.java 
b/java/org/apache/catalina/connector/CoyoteReader.java
index 1b23f33083..2620226b20 100644
--- a/java/org/apache/catalina/connector/CoyoteReader.java
+++ b/java/org/apache/catalina/connector/CoyoteReader.java
@@ -57,6 +57,9 @@ public class CoyoteReader extends BufferedReader {
      * @param ib The underlying input buffer
      */
     public CoyoteReader(InputBuffer ib) {
+        // BufferedReader requires a non-zero buffer size. All read operations 
are
+        // overridden to delegate directly to InputBuffer, so the parent 
buffer is
+        // never used. Size of 1 minimizes the allocation.
         super(ib, 1);
         this.ib = ib;
     }
diff --git a/java/org/apache/catalina/connector/CoyoteWriter.java 
b/java/org/apache/catalina/connector/CoyoteWriter.java
index 5f036d429a..0cfc488aa8 100644
--- a/java/org/apache/catalina/connector/CoyoteWriter.java
+++ b/java/org/apache/catalina/connector/CoyoteWriter.java
@@ -118,7 +118,6 @@ public class CoyoteWriter extends PrintWriter {
         } catch (IOException ignore) {
             // Ignore
         }
-        error = false;
 
     }
 
diff --git a/java/org/apache/catalina/connector/Request.java 
b/java/org/apache/catalina/connector/Request.java
index ae19b2e1d6..2ab88e0da9 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -1496,6 +1496,9 @@ public class Request implements HttpServletRequest {
      */
     private void notifyAttributeRemoved(String name, Object value) {
         Context context = getContext();
+        if (context == null) {
+            return;
+        }
         Object[] listeners = context.getApplicationEventListeners();
         if (listeners == null || listeners.length == 0) {
             return;
@@ -3037,7 +3040,7 @@ public class Request implements HttpServletRequest {
         int len = 0;
         while (len > -1) {
             len = getStream().read(buffer, 0, CACHED_POST_LEN);
-            if (connector.getMaxPostSize() >= 0 && (body.getLength() + len) > 
connector.getMaxPostSize()) {
+            if (connector.getMaxPostSize() >= 0 && ((long) body.getLength() + 
len) > connector.getMaxPostSize()) {
                 // Too much data
                 checkSwallowInput();
                 throw new 
InvalidParameterException(sm.getString("coyoteRequest.chunkedPostTooLarge"),
diff --git a/java/org/apache/catalina/connector/Response.java 
b/java/org/apache/catalina/connector/Response.java
index 0d497d0c78..6b9229c64b 100644
--- a/java/org/apache/catalina/connector/Response.java
+++ b/java/org/apache/catalina/connector/Response.java
@@ -901,6 +901,9 @@ public class Response implements HttpServletResponse {
         }
 
         String header = generateCookieString(cookie);
+        if (header == null) {
+            return;
+        }
         // if we reached here, no exception, cookie is valid
         addHeader("Set-Cookie", header, 
getContext().getCookieProcessor().getCharset());
     }
@@ -919,6 +922,9 @@ public class Response implements HttpServletResponse {
         final String headername = "Set-Cookie";
         final String startsWith = name + "=";
         String header = generateCookieString(cookie);
+        if (header == null) {
+            return;
+        }
         boolean set = false;
         MimeHeaders headers = getCoyoteResponse().getMimeHeaders();
         int n = headers.size();
@@ -944,9 +950,14 @@ public class Response implements HttpServletResponse {
      * @return The cookie header string
      */
     public String generateCookieString(final Cookie cookie) {
-        // Web application code can receive a IllegalArgumentException
-        // from the generateHeader() invocation
-        return getContext().getCookieProcessor().generateHeader(cookie, 
request.getRequest());
+        Context context = getContext();
+        if (context != null) {
+            // Web application code can receive a IllegalArgumentException
+            // from the generateHeader() invocation
+            return context.getCookieProcessor().generateHeader(cookie, 
request.getRequest());
+        } else {
+            return null;
+        }
     }
 
 
diff --git a/java/org/apache/catalina/connector/ResponseFacade.java 
b/java/org/apache/catalina/connector/ResponseFacade.java
index fe607b3dd1..1ebf9d9489 100644
--- a/java/org/apache/catalina/connector/ResponseFacade.java
+++ b/java/org/apache/catalina/connector/ResponseFacade.java
@@ -122,18 +122,14 @@ public class ResponseFacade implements 
HttpServletResponse {
 
     @Override
     public ServletOutputStream getOutputStream() throws IOException {
-        if (isFinished()) {
-            response.setSuspended(true);
-        }
+        checkFacade();
         return response.getOutputStream();
     }
 
 
     @Override
     public PrintWriter getWriter() throws IOException {
-        if (isFinished()) {
-            response.setSuspended(true);
-        }
+        checkFacade();
         return response.getWriter();
     }
 
diff --git a/java/org/apache/catalina/core/AccessLogAdapter.java 
b/java/org/apache/catalina/core/AccessLogAdapter.java
index 64afeb513e..38a3f62aeb 100644
--- a/java/org/apache/catalina/core/AccessLogAdapter.java
+++ b/java/org/apache/catalina/core/AccessLogAdapter.java
@@ -66,8 +66,12 @@ public class AccessLogAdapter implements AccessLog {
 
     @Override
     public boolean getRequestAttributesEnabled() {
-        // NOOP. Could return logs[0].getRequestAttributesEnabled(), but I do
-        // not see a use case for that.
+        for (AccessLog log : logs) {
+            // Return true if any AccessLog is going to use the attributes
+            if (log.getRequestAttributesEnabled()) {
+                return true;
+            }
+        }
         return false;
     }
 }
diff --git a/java/org/apache/catalina/realm/GenericPrincipal.java 
b/java/org/apache/catalina/realm/GenericPrincipal.java
index 7a3ce603b4..ad39e36563 100644
--- a/java/org/apache/catalina/realm/GenericPrincipal.java
+++ b/java/org/apache/catalina/realm/GenericPrincipal.java
@@ -223,6 +223,25 @@ public class GenericPrincipal implements TomcatPrincipal, 
Serializable {
     }
 
 
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        GenericPrincipal that = (GenericPrincipal) obj;
+        return Objects.equals(this.name, that.name);
+    }
+
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+
+
     @Override
     public void logout() throws Exception {
         if (loginContext != null) {
diff --git 
a/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java 
b/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java
index aaa65fd0c1..183a653372 100644
--- a/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java
+++ b/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java
@@ -58,6 +58,10 @@ public class BackportTranslations extends BackportBase {
             }
 
             Properties sourceTranslated = sourceTranslations.get(language);
+            if (sourceTranslated == null) {
+                sourceTranslated = new Properties();
+                sourceTranslations.put(language, sourceTranslated);
+            }
             Properties targetTranslated = targetTranslations.get(language);
             if (targetTranslated == null) {
                 targetTranslated = new Properties();
@@ -66,7 +70,6 @@ public class BackportTranslations extends BackportBase {
 
             for (Object key : targetEnglish.keySet()) {
                 if (sourceTranslated.containsKey(key) && 
targetEnglish.get(key).equals(sourceEnglish.get(key))) {
-
                     targetTranslated.put(key, sourceTranslated.get(key));
                 }
             }
diff --git a/java/org/apache/tomcat/buildutil/translate/Import.java 
b/java/org/apache/tomcat/buildutil/translate/Import.java
index 4fce11cd59..0f562309a3 100644
--- a/java/org/apache/tomcat/buildutil/translate/Import.java
+++ b/java/org/apache/tomcat/buildutil/translate/Import.java
@@ -89,6 +89,7 @@ public class Import {
                 }
                 File outFile = new File(currentPkg.replace('.', 
File.separatorChar),
                         Constants.L10N_PREFIX + language + 
Constants.L10N_SUFFIX);
+                // fos will be closed through w if w is replaced by another one
                 FileOutputStream fos = new FileOutputStream(outFile);
                 w = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
                 org.apache.tomcat.buildutil.Utils.insertLicense(w);
diff --git a/threadpool.patch b/threadpool.patch
new file mode 100644
index 0000000000..97b3afcecc
--- /dev/null
+++ b/threadpool.patch
@@ -0,0 +1,63 @@
+diff --git 
a/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java 
b/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java
+index 0451582..785a352 100644
+--- a/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java
++++ b/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java
+@@ -610,7 +610,7 @@
+         }
+ 
+         if (create) {
+-            collection.addPattern(urlPattern);
++            collection.addPatternDecoded(urlPattern);
+             constraint.addCollection(collection);
+             return constraint;
+         }
+diff --git a/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java 
b/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java
+index 6c61572..3a6636f 100644
+--- a/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java
++++ b/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java
+@@ -662,6 +662,11 @@
+      * ScheduledThreadPoolExecutor.
+      */
+     final void reject(Runnable command) {
++        // Decrement before calling the handler so non-throwing handlers
++        // (DiscardPolicy, CallerRunsPolicy, DiscardOldestPolicy) don't leak
++        // submittedCount. If the handler throws, the decrement is accounted
++        // for in the catch block of execute().
++        submittedCount.decrementAndGet();
+         handler.rejectedExecution(command, this);
+     }
+ 
+@@ -1102,11 +1107,13 @@
+                 // TaskQueue) in some tasks being rejected rather than queued.
+                 // If this happens, add them to the queue.
+                 if (!queue.force(command)) {
+-                    submittedCount.decrementAndGet();
+                     throw new 
RejectedExecutionException(sm.getString("threadPoolExecutor.queueFull"));
+                 }
++                // Task was force-queued and will run through a worker, so
++                // afterExecute() will decrement. Re-increment to cancel the
++                // decrement that was done in reject() before the handler 
threw.
++                submittedCount.incrementAndGet();
+             } else {
+-                submittedCount.decrementAndGet();
+                 throw rx;
+             }
+         }
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 24b0d72..4e92dd0 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -415,6 +415,12 @@
+         <code>isTrailerFieldsReady</code> was always returning
+         <code>true</code>. (remm)
+       </fix>
++      <fix>
++        Fix <code>submittedCount</code> leak with the thread pool when using
++        non default <code>RejectedExecutionHandler</code>. The default handler
++        is throwing an exception on rejection and was processed properly.
++        (remm)
++      </fix>
+     </changelog>
+   </subsection>
+   <subsection name="Jasper">
+


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to