You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/09/29 18:49:17 UTC

(tomcat) branch 11.0.x updated (5ee1097e13 -> 21d8a2b6d9)

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

rmaucher pushed a change to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


    from 5ee1097e13 Avoid very rare race between async write notification and completion
     new c9e88e9481 Fix FindLeaksTask response constraint handling when statusLine is false
     new 84f4468c91 Remove unused internalid attribute from JKStatusUpdateTask
     new ab1757757a Add configurable timeout for HTTP connections used by the Manager Ant tasks
     new a474f16ee3 Avoid buffering remote WAR uploads of unknown length in memory in the Manager Ant tasks
     new 27e28fc0a5 Align default URL-encoding charset of the Manager Ant tasks with the server default of UTF-8
     new 66093d0f9e Include the HTTP error response body in the error messages of the Manager Ant tasks
     new 527314bd98 Prevent oversized 'idle' values from expiring all sessions via integer overflow in the sessions/expire command
     new aacb2cd4d7 Register the missing serverinfo Ant task in antlib.xml and catalina.tasks
     new 655ef8e8f0 Match the runtime default by blocking external entity resolution in the Validator Ant task
     new 04cf4fb09f Close the JMX connection owned by a task or condition when no reference is used to share it
     new 2bc2bc5c13 Fail with a clear BuildException when a JMX string-to-type conversion is impossible instead of sending the raw String to the server
     new 7b0a9f83c3 Validate the operation and type in the JMX condition and report non-numeric values as a BuildException instead of an uncaught NumberFormatException or a silent false
     new 442a363564 Raise a BuildException when a JMX task or condition explicitly specifies a target that conflicts with an existing connection reference instead of silently ignoring it
     new 21d8a2b6d9 Log the error message returned by a JMX task when failOnError is false instead of discarding it

The 14 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/catalina/ant/AbstractCatalinaTask.java  |  68 ++++++-
 java/org/apache/catalina/ant/DeployTask.java       |   4 +
 java/org/apache/catalina/ant/FindLeaksTask.java    |   3 +
 .../apache/catalina/ant/JKStatusUpdateTask.java    |  20 --
 java/org/apache/catalina/ant/SessionsTask.java     |   7 +-
 java/org/apache/catalina/ant/ValidatorTask.java    |   2 +-
 java/org/apache/catalina/ant/antlib.xml            |   3 +
 java/org/apache/catalina/ant/catalina.tasks        |   1 +
 .../catalina/ant/jmx/JMXAccessorCondition.java     |  81 +++++---
 .../catalina/ant/jmx/JMXAccessorConditionBase.java |  46 ++++-
 .../catalina/ant/jmx/JMXAccessorSetTask.java       |   4 +
 .../apache/catalina/ant/jmx/JMXAccessorTask.java   | 214 +++++++++++++++------
 .../apache/catalina/manager/ManagerServlet.java    |   2 +-
 .../catalina/ant/jmx/TestJMXAccessorCondition.java |  62 ++++++
 .../catalina/ant/jmx/TestJMXAccessorTask.java      | 108 +++++++++++
 15 files changed, 505 insertions(+), 120 deletions(-)
 create mode 100644 test/org/apache/catalina/ant/jmx/TestJMXAccessorCondition.java


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


(tomcat) 04/14: Avoid buffering remote WAR uploads of unknown length in memory in the Manager Ant tasks

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit a474f16ee34b6257fac766a5cf7cdb5a6a532aa6
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:09:16 2026 +0200

    Avoid buffering remote WAR uploads of unknown length in memory in the Manager Ant tasks
---
 java/org/apache/catalina/ant/AbstractCatalinaTask.java | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/java/org/apache/catalina/ant/AbstractCatalinaTask.java b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
index 58d078de29..bf20a8ae35 100644
--- a/java/org/apache/catalina/ant/AbstractCatalinaTask.java
+++ b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
@@ -274,6 +274,11 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
                     hconn.setRequestProperty("Content-Length", "" + contentLength);
 
                     hconn.setFixedLengthStreamingMode(contentLength);
+                } else {
+                    // The length is unknown. Use chunked streaming to avoid the
+                    // default HttpURLConnection behaviour of buffering the
+                    // entire request body in memory.
+                    hconn.setChunkedStreamingMode(0);
                 }
             } else {
                 hconn.setDoOutput(false);


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


(tomcat) 10/14: Close the JMX connection owned by a task or condition when no reference is used to share it

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 04cf4fb09f2927e82c1ba4363f033d8f101f6cb1
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:26:31 2026 +0200

    Close the JMX connection owned by a task or condition when no reference is used to share it
---
 .../catalina/ant/jmx/JMXAccessorConditionBase.java | 37 +++++++++-
 .../apache/catalina/ant/jmx/JMXAccessorTask.java   | 82 +++++++++++++++++-----
 2 files changed, 98 insertions(+), 21 deletions(-)

diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java b/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
index 6d08cd478e..084daf5b03 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
@@ -21,6 +21,7 @@ import java.net.MalformedURLException;
 
 import javax.management.MBeanServerConnection;
 import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
 
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.taskdefs.condition.Condition;
@@ -46,6 +47,12 @@ public abstract class JMXAccessorConditionBase extends ProjectComponent implemen
     private String value;
     private String ref = "jmx.server";
 
+    /*
+     * Connector created for the current evaluation when the connection is not shared through a project reference. It
+     * is closed once the value has been read so repeated waitfor evaluations do not accumulate connections.
+     */
+    private JMXConnector jmxConnector;
+
     /**
      * Get the attribute name.
      *
@@ -217,8 +224,29 @@ public abstract class JMXAccessorConditionBase extends ProjectComponent implemen
      * @throws IOException           Connection error
      */
     protected MBeanServerConnection getJMXConnection() throws MalformedURLException, IOException {
-        return JMXAccessorTask.accessJMXConnection(getProject(), getUrl(), getHost(), getPort(), getUsername(),
-                getPassword(), ref);
+        if (ref != null && !ref.isEmpty() && getProject() != null) {
+            // Reuse or establish a shared connection stored in the project reference; this condition does not own it.
+            return JMXAccessorTask.accessJMXConnection(getProject(), getUrl(), getHost(), getPort(), getUsername(),
+                    getPassword(), ref);
+        }
+        // No reference to store it in: this condition owns the connection and closes it after the evaluation.
+        jmxConnector = JMXAccessorTask.createJMXConnector(getUrl(), getHost(), getPort(), getUsername(), getPassword());
+        return jmxConnector.getMBeanServerConnection();
+    }
+
+    /**
+     * Close the JMX connection owned by this condition, if any. Connections shared through a project reference are
+     * left open for reuse.
+     */
+    private void closeJMXConnector() {
+        if (jmxConnector != null) {
+            try {
+                jmxConnector.close();
+            } catch (IOException e) {
+                // Ignore errors while closing
+            }
+            jmxConnector = null;
+        }
     }
 
     /**
@@ -228,7 +256,8 @@ public abstract class JMXAccessorConditionBase extends ProjectComponent implemen
      */
     protected String accessJMXValue() {
         try {
-            Object result = getJMXConnection().getAttribute(new ObjectName(name), attribute);
+            MBeanServerConnection jmxServerConnection = getJMXConnection();
+            Object result = jmxServerConnection.getAttribute(new ObjectName(name), attribute);
             if (result != null) {
                 return result.toString();
             }
@@ -237,6 +266,8 @@ public abstract class JMXAccessorConditionBase extends ProjectComponent implemen
              * Exceptions are ignored for compatibility with the waitFor task when waiting for the server to start. If
              * the exception was thrown the build task would fail rather than wait.
              */
+        } finally {
+            closeJMXConnector();
         }
         return null;
     }
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
index 91d66c4ef8..4a80078fde 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
@@ -125,6 +125,12 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
 
     private final Properties properties = new Properties();
 
+    /*
+     * Connector owned by this task for the duration of a single execution. Only set when the connection was created
+     * by this task and is not shared via a project reference, so it can be closed when the task completes.
+     */
+    private JMXConnector jmxConnector;
+
     // ------------------------------------------------------------- Properties
 
     /**
@@ -398,6 +404,7 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
                     handleErrorOutput(e.getMessage());
                 }
             } finally {
+                closeJMXConnector();
                 closeRedirector();
             }
         }
@@ -420,6 +427,29 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
      */
     public static MBeanServerConnection createJMXConnection(String url, String host, String port, String username,
             String password) throws MalformedURLException, IOException {
+        return createJMXConnector(url, host, port, username, password).getMBeanServerConnection();
+    }
+
+    /**
+     * Create a new JMX Connection with auth when username and password is set. The caller is responsible for closing
+     * the returned connector.
+     *
+     * @param url      URL to be used for the JMX connection (if specified, it is a complete URL so host and port will
+     *                     not be used)
+     * @param host     Host name of the JMX server
+     * @param port     Port number for the JMX server
+     * @param username User name for the connection
+     * @param password Credentials corresponding to the specified user
+     *
+     * @throws MalformedURLException Invalid URL specified
+     * @throws IOException           Other connection error
+     *
+     * @return the JMX connector
+     *
+     * @since 12.0.x
+     */
+    public static JMXConnector createJMXConnector(String url, String host, String port, String username,
+            String password) throws MalformedURLException, IOException {
         String urlForJMX;
         if (url != null) {
             urlForJMX = url;
@@ -434,9 +464,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();
-
+        return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX), environment);
     }
 
     /**
@@ -515,30 +543,48 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
      */
     protected MBeanServerConnection getJMXConnection() throws MalformedURLException, IOException {
         MBeanServerConnection jmxServerConnection = null;
-        if (isUseRef()) {
-            Object pref;
-            if (getProject() != null) {
-                pref = getProject().getReference(getRef());
-                if (pref != null) {
-                    try {
-                        jmxServerConnection = (MBeanServerConnection) pref;
-                    } catch (ClassCastException cce) {
-                        getProject().log("Wrong object reference " + getRef() + " - " + pref.getClass());
-                        return null;
-                    }
+        boolean refAvailable = isUseRef() && getProject() != null;
+        if (refAvailable) {
+            Object pref = getProject().getReference(getRef());
+            if (pref != null) {
+                try {
+                    jmxServerConnection = (MBeanServerConnection) pref;
+                } catch (ClassCastException cce) {
+                    getProject().log("Wrong object reference " + getRef() + " - " + pref.getClass());
+                    return null;
                 }
             }
-            if (jmxServerConnection == null) {
+        }
+        if (jmxServerConnection == null) {
+            if (refAvailable) {
+                // A reference is available: the connection is stored in the project for reuse by later tasks in
+                // the same build and is intentionally left open, so this task does not own it.
                 jmxServerConnection = accessJMXConnection(getProject(), getUrl(), getHost(), getPort(), getUsername(),
                         getPassword(), getRef());
+            } else {
+                // No reference to store it in: this task owns the connection and closes it when it completes.
+                jmxConnector = createJMXConnector(getUrl(), getHost(), getPort(), getUsername(), getPassword());
+                jmxServerConnection = jmxConnector.getMBeanServerConnection();
             }
-        } else {
-            jmxServerConnection = accessJMXConnection(getProject(), getUrl(), getHost(), getPort(), getUsername(),
-                    getPassword(), null);
         }
         return jmxServerConnection;
     }
 
+    /**
+     * Close the JMX connection owned by this task, if any. Connections shared through a project reference are not
+     * owned by this task and are left open for reuse.
+     */
+    private void closeJMXConnector() {
+        if (jmxConnector != null) {
+            try {
+                jmxConnector.close();
+            } catch (IOException e) {
+                // Ignore errors while closing
+            }
+            jmxConnector = null;
+        }
+    }
+
     /**
      * Execute the specified command, based on the configured properties.
      *


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


(tomcat) 03/14: Add configurable timeout for HTTP connections used by the Manager Ant tasks

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ab1757757a28cf2d964de4d53221bcb7c3c41a54
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 18:28:45 2026 +0200

    Add configurable timeout for HTTP connections used by the Manager Ant tasks
---
 .../apache/catalina/ant/AbstractCatalinaTask.java  | 34 ++++++++++++++++++++++
 java/org/apache/catalina/ant/DeployTask.java       |  4 +++
 2 files changed, 38 insertions(+)

diff --git a/java/org/apache/catalina/ant/AbstractCatalinaTask.java b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
index 5fc185117c..58d078de29 100644
--- a/java/org/apache/catalina/ant/AbstractCatalinaTask.java
+++ b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
@@ -96,6 +96,32 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
     }
 
 
+    /**
+     * The timeout, in seconds, used when establishing a connection to the server and when reading data from it. The
+     * default value of zero means no timeout, in which case an unresponsive server may cause the build to block
+     * indefinitely.
+     */
+    protected int timeout = 0;
+
+    /**
+     * Returns the connection and read timeout, in seconds.
+     *
+     * @return the timeout in seconds; zero means no timeout
+     */
+    public int getTimeout() {
+        return this.timeout;
+    }
+
+    /**
+     * Sets the connection and read timeout, in seconds.
+     *
+     * @param timeout the timeout in seconds; zero (the default) means no timeout
+     */
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+
     /**
      * The URL of the <code>Manager</code> application to be used.
      */
@@ -227,6 +253,10 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
             hconn.setAllowUserInteraction(false);
             hconn.setDoInput(true);
             hconn.setUseCaches(false);
+            if (timeout > 0) {
+                hconn.setConnectTimeout(timeout * 1000);
+                hconn.setReadTimeout(timeout * 1000);
+            }
 
             // Set up authorization with our credentials
             Authenticator authenticator = new TaskAuthenticator(username, password);
@@ -346,6 +376,10 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
         hconn.setAllowUserInteraction(false);
         hconn.setDoInput(true);
         hconn.setUseCaches(false);
+        if (timeout > 0) {
+            hconn.setConnectTimeout(timeout * 1000);
+            hconn.setReadTimeout(timeout * 1000);
+        }
         hconn.setDoOutput(false);
         hconn.setAuthenticator(authenticator);
         hconn.setRequestMethod(Method.OPTIONS);
diff --git a/java/org/apache/catalina/ant/DeployTask.java b/java/org/apache/catalina/ant/DeployTask.java
index 9b26a31a7f..6595b20d9e 100644
--- a/java/org/apache/catalina/ant/DeployTask.java
+++ b/java/org/apache/catalina/ant/DeployTask.java
@@ -188,6 +188,10 @@ public class DeployTask extends AbstractCatalinaCommandTask {
                 try {
                     URI uri = new URI(war);
                     URLConnection conn = uri.toURL().openConnection();
+                    if (timeout > 0) {
+                        conn.setConnectTimeout(timeout * 1000);
+                        conn.setReadTimeout(timeout * 1000);
+                    }
                     contentLength = conn.getContentLengthLong();
                     stream = new BufferedInputStream(conn.getInputStream(), 1024);
                 } catch (IOException | URISyntaxException e) {


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


(tomcat) 14/14: Log the error message returned by a JMX task when failOnError is false instead of discarding it

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 21d8a2b6d976efd2d1a5e8e9b5ea8812f596bbc3
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:43:54 2026 +0200

    Log the error message returned by a JMX task when failOnError is false instead of discarding it
---
 java/org/apache/catalina/ant/jmx/JMXAccessorTask.java | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
index d6b71df30d..d9a63f2220 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
@@ -403,10 +403,14 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
 
                 MBeanServerConnection jmxServerConnection = getJMXConnection();
                 error = jmxExecute(jmxServerConnection);
-                if (error != null && isFailOnError()) {
-                    // exception should be thrown only if failOnError == true
-                    // or error line will be logged twice
-                    throw new BuildException(error);
+                if (error != null) {
+                    if (isFailOnError()) {
+                        // exception should be thrown only if failOnError == true
+                        // or error line will be logged twice
+                        throw new BuildException(error);
+                    }
+                    // Ant semantics for failOnError="false" are to report the error and continue
+                    handleErrorOutput(error);
                 }
             } catch (Exception e) {
                 if (isFailOnError()) {


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


(tomcat) 12/14: Validate the operation and type in the JMX condition and report non-numeric values as a BuildException instead of an uncaught NumberFormatException or a silent false

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7b0a9f83c3b2c62d5d4000a7cb3f4ace901183e1
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:32:05 2026 +0200

    Validate the operation and type in the JMX condition and report non-numeric values as a BuildException instead of an uncaught NumberFormatException or a silent false
---
 .../catalina/ant/jmx/JMXAccessorCondition.java     | 81 ++++++++++++++--------
 .../catalina/ant/jmx/TestJMXAccessorCondition.java | 62 +++++++++++++++++
 2 files changed, 116 insertions(+), 27 deletions(-)

diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java b/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java
index b09a323546..56415ebeec 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java
@@ -212,38 +212,65 @@ public class JMXAccessorCondition extends JMXAccessorConditionBase {
             throw new BuildException("Must specify an MBean name and attribute for condition");
         }
         if (testIfCondition() && testUnlessCondition()) {
+            String op = getOperation();
+            boolean equals = "==".equals(op);
+            boolean notEquals = "!=".equals(op);
+            boolean greater = ">".equals(op);
+            boolean greaterOrEquals = ">=".equals(op);
+            boolean lesser = "<".equals(op);
+            boolean lesserOrEquals = "<=".equals(op);
+            if (!equals && !notEquals && !greater && !greaterOrEquals && !lesser && !lesserOrEquals) {
+                throw new BuildException("Unsupported operation '" + op +
+                        "'. Supported operations are ==, !=, >, >=, < and <=.");
+            }
+            boolean relational = !equals && !notEquals;
+            if (relational && !"long".equals(type) && !"double".equals(type)) {
+                throw new BuildException("Unsupported type '" + type + "' for operation '" + op +
+                        "'. Supported types for relational operations are long and double.");
+            }
             String jmxValue = accessJMXValue();
             if (jmxValue != null) {
-                String op = getOperation();
-                if ("==".equals(op)) {
+                if (equals) {
                     return jmxValue.equals(value);
-                } else if ("!=".equals(op)) {
+                } else if (notEquals) {
                     return !jmxValue.equals(value);
+                } else if ("double".equals(type)) {
+                    double jvalue;
+                    double dvalue;
+                    try {
+                        jvalue = Double.parseDouble(jmxValue);
+                        dvalue = Double.parseDouble(value);
+                    } catch (NumberFormatException e) {
+                        throw new BuildException("Unable to compare the JMX attribute value '" + jmxValue +
+                                "' with the expected value '" + value + "' as a double", e);
+                    }
+                    if (greater) {
+                        return jvalue > dvalue;
+                    } else if (greaterOrEquals) {
+                        return jvalue >= dvalue;
+                    } else if (lesser) {
+                        return jvalue < dvalue;
+                    } else {
+                        return jvalue <= dvalue;
+                    }
                 } else {
-                    if ("long".equals(type)) {
-                        long jvalue = Long.parseLong(jmxValue);
-                        long lvalue = Long.parseLong(value);
-                        if (">".equals(op)) {
-                            return jvalue > lvalue;
-                        } else if (">=".equals(op)) {
-                            return jvalue >= lvalue;
-                        } else if ("<".equals(op)) {
-                            return jvalue < lvalue;
-                        } else if ("<=".equals(op)) {
-                            return jvalue <= lvalue;
-                        }
-                    } else if ("double".equals(type)) {
-                        double jvalue = Double.parseDouble(jmxValue);
-                        double dvalue = Double.parseDouble(value);
-                        if (">".equals(op)) {
-                            return jvalue > dvalue;
-                        } else if (">=".equals(op)) {
-                            return jvalue >= dvalue;
-                        } else if ("<".equals(op)) {
-                            return jvalue < dvalue;
-                        } else if ("<=".equals(op)) {
-                            return jvalue <= dvalue;
-                        }
+                    long jvalue;
+                    long lvalue;
+                    try {
+                        jvalue = Long.parseLong(jmxValue);
+                        lvalue = Long.parseLong(value);
+                    } catch (NumberFormatException e) {
+                        throw new BuildException("Unable to compare the JMX attribute value '" + jmxValue +
+                                "' with the expected value '" + value + "' as a long", e);
+                    }
+                    if (greater) {
+                        return jvalue > lvalue;
+                    } else if (greaterOrEquals) {
+                        return jvalue >= lvalue;
+                    } else if (lesser) {
+                        return jvalue < lvalue;
+                    } else {
+                        return jvalue <= lvalue;
                     }
                 }
             }
diff --git a/test/org/apache/catalina/ant/jmx/TestJMXAccessorCondition.java b/test/org/apache/catalina/ant/jmx/TestJMXAccessorCondition.java
new file mode 100644
index 0000000000..bdf02c8cfe
--- /dev/null
+++ b/test/org/apache/catalina/ant/jmx/TestJMXAccessorCondition.java
@@ -0,0 +1,62 @@
+/*
+ * 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.catalina.ant.jmx;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.tools.ant.BuildException;
+
+public class TestJMXAccessorCondition {
+
+    @Test
+    public void testEvalUnsupportedOperation() {
+        JMXAccessorCondition condition = createCondition();
+        condition.setOperation(">>=");
+
+        try {
+            condition.eval();
+            Assert.fail("Expected a BuildException for an unsupported operation");
+        } catch (BuildException expected) {
+            // Expected
+        }
+    }
+
+
+    @Test
+    public void testEvalUnsupportedTypeForRelationalOperation() {
+        JMXAccessorCondition condition = createCondition();
+        condition.setOperation("<");
+        condition.setType("string");
+
+        try {
+            condition.eval();
+            Assert.fail("Expected a BuildException for an unsupported type");
+        } catch (BuildException expected) {
+            // Expected
+        }
+    }
+
+
+    private static JMXAccessorCondition createCondition() {
+        JMXAccessorCondition condition = new JMXAccessorCondition();
+        condition.setName("Catalina:type=Test");
+        condition.setAttribute("startupTime");
+        condition.setValue("250");
+        return condition;
+    }
+}


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


(tomcat) 09/14: Match the runtime default by blocking external entity resolution in the Validator Ant task

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 655ef8e8f086944a6b065fa0e99620b26cacbea6
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:16:34 2026 +0200

    Match the runtime default by blocking external entity resolution in the Validator Ant task
---
 java/org/apache/catalina/ant/ValidatorTask.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/ant/ValidatorTask.java b/java/org/apache/catalina/ant/ValidatorTask.java
index 201d931119..4ee955f43c 100644
--- a/java/org/apache/catalina/ant/ValidatorTask.java
+++ b/java/org/apache/catalina/ant/ValidatorTask.java
@@ -97,7 +97,7 @@ public class ValidatorTask extends BaseRedirectorHelperTask {
         ClassLoader oldCL = currentThread.getContextClassLoader();
         currentThread.setContextClassLoader(ValidatorTask.class.getClassLoader());
 
-        Digester digester = DigesterFactory.newDigester(true, true, null, false);
+        Digester digester = DigesterFactory.newDigester(true, true, null, true);
         try (InputStream stream = new BufferedInputStream(new FileInputStream(file.getCanonicalFile()))) {
             InputSource is = new InputSource(file.toURI().toURL().toExternalForm());
             is.setByteStream(stream);


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


(tomcat) 02/14: Remove unused internalid attribute from JKStatusUpdateTask

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 84f4468c911fadfca2611328bd264df438d60234
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 18:11:50 2026 +0200

    Remove unused internalid attribute from JKStatusUpdateTask
---
 java/org/apache/catalina/ant/JKStatusUpdateTask.java | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/java/org/apache/catalina/ant/JKStatusUpdateTask.java b/java/org/apache/catalina/ant/JKStatusUpdateTask.java
index 767a88bf8b..9e671334ea 100644
--- a/java/org/apache/catalina/ant/JKStatusUpdateTask.java
+++ b/java/org/apache/catalina/ant/JKStatusUpdateTask.java
@@ -32,8 +32,6 @@ public class JKStatusUpdateTask extends AbstractCatalinaTask {
 
     private String workerType = "lb";
 
-    private int internalid = 0;
-
     private Integer lbRetries;
 
     private Integer lbRecovertime;
@@ -64,24 +62,6 @@ public class JKStatusUpdateTask extends AbstractCatalinaTask {
         setUrl("http://localhost/status");
     }
 
-    /**
-     * Get the internal ID.
-     *
-     * @return the internal ID
-     */
-    public int getInternalid() {
-        return internalid;
-    }
-
-    /**
-     * Set the internal ID.
-     *
-     * @param internalid the internal ID to set
-     */
-    public void setInternalid(int internalid) {
-        this.internalid = internalid;
-    }
-
     /**
      * Get the lbForceSession flag.
      *


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


(tomcat) 13/14: Raise a BuildException when a JMX task or condition explicitly specifies a target that conflicts with an existing connection reference instead of silently ignoring it

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 442a363564472ff2bdfc6c6d547954afcda04d5d
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:37:47 2026 +0200

    Raise a BuildException when a JMX task or condition explicitly specifies a target that conflicts with an existing connection reference instead of silently ignoring it
---
 .../catalina/ant/jmx/JMXAccessorConditionBase.java |  9 ++-
 .../apache/catalina/ant/jmx/JMXAccessorTask.java   | 80 +++++++++++++++++-----
 .../catalina/ant/jmx/TestJMXAccessorTask.java      | 63 +++++++++++++++++
 3 files changed, 132 insertions(+), 20 deletions(-)

diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java b/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
index 084daf5b03..be21134b5d 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorConditionBase.java
@@ -38,8 +38,13 @@ public abstract class JMXAccessorConditionBase extends ProjectComponent implemen
     }
 
     private String url = null;
-    private String host = "localhost";
-    private String port = "8050";
+    /*
+     * A null host or port means the attribute was not specified. The defaults (localhost and 8050) are applied when
+     * the JMX service URL is built, so an explicitly specified value can be detected and compared against an existing
+     * connection reference.
+     */
+    private String host = null;
+    private String port = null;
     private String password = null;
     private String username = null;
     private String name = null;
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
index 5e7dd9884f..d6b71df30d 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
@@ -95,6 +95,12 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
      */
     public static final String JMX_SERVICE_SUFFIX = "/jmxrmi";
 
+    /*
+     * Suffix of the project reference under which the JMX service URL of a connection stored under reference
+     * <em>refId</em> is recorded, to be able to detect later requests that explicitly specify a different target.
+     */
+    private static final String JMX_SERVICE_URL_REF_SUFFIX = "-jmx-service-url";
+
     // ----------------------------------------------------- Instance Variables
 
     private String name = null;
@@ -103,9 +109,14 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
 
     private String url = null;
 
-    private String host = "localhost";
+    /*
+     * A null host or port means the attribute was not specified. The defaults (localhost and 8050) are applied when
+     * the JMX service URL is built, so an explicitly specified value can be detected and compared against an existing
+     * connection reference.
+     */
+    private String host = null;
 
-    private String port = "8050";
+    private String port = null;
 
     private String password = null;
 
@@ -436,8 +447,8 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
      *
      * @param url      URL to be used for the JMX connection (if specified, it is a complete URL so host and port will
      *                     not be used)
-     * @param host     Host name of the JMX server
-     * @param port     Port number for the JMX server
+     * @param host     Host name of the JMX server ({@code null} selects the default host)
+     * @param port     Port number for the JMX server ({@code null} selects the default port)
      * @param username User name for the connection
      * @param password Credentials corresponding to the specified user
      *
@@ -450,12 +461,7 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
      */
     public static JMXConnector createJMXConnector(String url, String host, String port, String username,
             String password) throws MalformedURLException, IOException {
-        String urlForJMX;
-        if (url != null) {
-            urlForJMX = url;
-        } else {
-            urlForJMX = JMX_SERVICE_PREFIX + host + ":" + port + JMX_SERVICE_SUFFIX;
-        }
+        String urlForJMX = resolveJMXServiceURL(url, host, port);
         Map<String,String[]> environment = null;
         if (username != null && password != null) {
             String[] credentials = new String[2];
@@ -467,6 +473,30 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
         return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX), environment);
     }
 
+    /*
+     * Build the JMX service URL from the connection parameters, applying the default host and port when they are not
+     * specified.
+     */
+    private static String resolveJMXServiceURL(String url, String host, String port) {
+        if (url != null) {
+            return url;
+        }
+        String effectiveHost = host != null ? host : "localhost";
+        String effectivePort = port != null ? port : "8050";
+        return JMX_SERVICE_PREFIX + effectiveHost + ":" + effectivePort + JMX_SERVICE_SUFFIX;
+    }
+
+    /*
+     * The JMX service URL targeted by the given connection parameters, or null when no target was specified at all
+     * (in which case the parameters say nothing about which server the caller wants to reach).
+     */
+    private static String specifiedJMXServiceURL(String url, String host, String port) {
+        if (url == null && host == null && port == null) {
+            return null;
+        }
+        return resolveJMXServiceURL(url, host, port);
+    }
+
     /**
      * test the if condition
      *
@@ -515,18 +545,32 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
         boolean isRef = project != null && refId != null && !refId.isEmpty();
         if (isRef) {
             Object pref = project.getReference(refId);
-            try {
-                jmxServerConnection = (MBeanServerConnection) pref;
-            } catch (ClassCastException cce) {
-                project.log("wrong object reference " + refId + " - " + pref.getClass());
-                return null;
+            if (pref != null) {
+                try {
+                    jmxServerConnection = (MBeanServerConnection) pref;
+                } catch (ClassCastException cce) {
+                    project.log("wrong object reference " + refId + " - " + pref.getClass());
+                    return null;
+                }
+            }
+            if (jmxServerConnection != null) {
+                // The reference already holds an open connection and is reused. If this call explicitly specifies a
+                // different target, the explicit parameters would be silently ignored, so fail instead.
+                String specified = specifiedJMXServiceURL(url, host, port);
+                Object openedTo = project.getReference(refId + JMX_SERVICE_URL_REF_SUFFIX);
+                if (specified != null && openedTo != null && !specified.equals(openedTo)) {
+                    throw new BuildException("The JMX connection reference '" + refId + "' already refers to a "
+                            + "connection to '" + openedTo + "'. This task specifies a connection to '" + specified
+                            + "'. Open the second server under a different ref or omit the connection parameters "
+                            + "to reuse the existing connection.");
+                }
+                return jmxServerConnection;
             }
         }
-        if (jmxServerConnection == null) {
-            jmxServerConnection = createJMXConnection(url, host, port, username, password);
-        }
+        jmxServerConnection = createJMXConnection(url, host, port, username, password);
         if (isRef && jmxServerConnection != null) {
             project.addReference(refId, jmxServerConnection);
+            project.addReference(refId + JMX_SERVICE_URL_REF_SUFFIX, resolveJMXServiceURL(url, host, port));
         }
         return jmxServerConnection;
     }
diff --git a/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java b/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java
index b7104604d7..71927130c0 100644
--- a/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java
+++ b/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java
@@ -16,6 +16,14 @@
  */
 package org.apache.catalina.ant.jmx;
 
+import java.lang.management.ManagementFactory;
+import java.net.ServerSocket;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
 import javax.management.openmbean.CompositeDataSupport;
 import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.OpenDataException;
@@ -23,11 +31,15 @@ import javax.management.openmbean.OpenType;
 import javax.management.openmbean.SimpleType;
 import javax.management.openmbean.TabularDataSupport;
 import javax.management.openmbean.TabularType;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
 
 import org.junit.Assert;
 import org.junit.Test;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
 
 public class TestJMXAccessorTask {
 
@@ -89,6 +101,57 @@ public class TestJMXAccessorTask {
     }
 
 
+    /*
+     * A cached connection reference is reused. If the caller explicitly specifies a different target than the one the
+     * reference was opened to, a BuildException is raised instead of the explicit parameters being silently ignored.
+     */
+    @Test
+    public void testAccessJMXConnectionReuseAndMismatch() throws Exception {
+        int port = getAvailablePort();
+        Registry registry = LocateRegistry.createRegistry(port);
+        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+        JMXServiceURL serviceUrl = new JMXServiceURL(
+                JMXAccessorTask.JMX_SERVICE_PREFIX + "localhost:" + port + JMXAccessorTask.JMX_SERVICE_SUFFIX);
+        JMXConnectorServer connectorServer =
+                JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, null, mbeanServer);
+        connectorServer.start();
+        try {
+            Project project = new Project();
+            String ref = "jmx.server.test";
+            String host = "localhost";
+            String openPort = Integer.toString(port);
+
+            // First call opens the connection and stores it under the reference.
+            MBeanServerConnection first =
+                    JMXAccessorTask.accessJMXConnection(project, null, host, openPort, null, null, ref);
+            Assert.assertNotNull(first);
+
+            // Reuse with no explicit target: the cached connection is returned.
+            MBeanServerConnection reused =
+                    JMXAccessorTask.accessJMXConnection(project, null, null, null, null, null, ref);
+            Assert.assertSame(first, reused);
+
+            // Explicitly specifying a different port than the open connection must fail rather than be ignored.
+            try {
+                JMXAccessorTask.accessJMXConnection(project, null, host, "1", null, null, ref);
+                Assert.fail("Expected a BuildException for an explicit conflicting target");
+            } catch (BuildException expected) {
+                // Expected
+            }
+        } finally {
+            connectorServer.stop();
+            UnicastRemoteObject.unexportObject(registry, true);
+        }
+    }
+
+
+    private static int getAvailablePort() throws Exception {
+        try (ServerSocket socket = new ServerSocket(0)) {
+            return socket.getLocalPort();
+        }
+    }
+
+
     private static TabularDataSupport createTabularData() throws OpenDataException {
         CompositeType detailsType = new CompositeType("details", "details", new String[] { "name" },
                 new String[] { "name" }, new OpenType<?>[] { SimpleType.STRING });


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


(tomcat) 06/14: Include the HTTP error response body in the error messages of the Manager Ant tasks

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 66093d0f9ed5124c0175b53ed160a895ffef5ddb
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:09:16 2026 +0200

    Include the HTTP error response body in the error messages of the Manager Ant tasks
---
 .../apache/catalina/ant/AbstractCatalinaTask.java  | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/java/org/apache/catalina/ant/AbstractCatalinaTask.java b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
index fb5b9138e9..594b9215f6 100644
--- a/java/org/apache/catalina/ant/AbstractCatalinaTask.java
+++ b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
@@ -16,6 +16,7 @@
  */
 package org.apache.catalina.ant;
 
+import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -296,6 +297,32 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
                 }
             }
 
+            int responseCode = hconn.getResponseCode();
+            if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) {
+                // For error responses, getInputStream() below would throw and
+                // the response body - which typically explains the error -
+                // would be discarded. Include its first line in the message.
+                String errorBody = null;
+                try (InputStream errorStream = hconn.getErrorStream()) {
+                    if (errorStream != null) {
+                        BufferedReader errorReader = new BufferedReader(
+                                new InputStreamReader(errorStream, StandardCharsets.UTF_8));
+                        errorBody = errorReader.readLine();
+                    }
+                }
+                StringBuilder message = new StringBuilder();
+                message.append("Server returned HTTP response code: ");
+                message.append(responseCode);
+                message.append(" for URL: ");
+                message.append(url);
+                message.append(command);
+                if (errorBody != null && !errorBody.isEmpty()) {
+                    message.append(" - ");
+                    message.append(errorBody);
+                }
+                throw new IOException(message.toString());
+            }
+
             // Process the response message
             reader = new InputStreamReader(hconn.getInputStream(), StandardCharsets.UTF_8);
             StringBuilder buff = new StringBuilder();


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


(tomcat) 07/14: Prevent oversized 'idle' values from expiring all sessions via integer overflow in the sessions/expire command

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 527314bd98c0fb11c8b98a85e29697e80275e271
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:16:34 2026 +0200

    Prevent oversized 'idle' values from expiring all sessions via integer overflow in the sessions/expire command
---
 java/org/apache/catalina/ant/SessionsTask.java       | 7 ++++++-
 java/org/apache/catalina/manager/ManagerServlet.java | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/ant/SessionsTask.java b/java/org/apache/catalina/ant/SessionsTask.java
index a6bf92c602..94184c0eb4 100644
--- a/java/org/apache/catalina/ant/SessionsTask.java
+++ b/java/org/apache/catalina/ant/SessionsTask.java
@@ -65,7 +65,12 @@ public class SessionsTask extends AbstractCatalinaCommandTask {
         if (path != null && idle != null) {
             buffer.append("&idle=");
             try {
-                buffer.append(Integer.valueOf(idle));
+                int idleMinutes = Integer.parseInt(idle);
+                if (idleMinutes < 0 || idleMinutes > Integer.MAX_VALUE / 60) {
+                    throw new BuildException("Invalid 'idle' attribute (must be a non-negative integer no greater "
+                            + "than " + (Integer.MAX_VALUE / 60) + "): [" + idle + "]");
+                }
+                buffer.append(idleMinutes);
             } catch (NumberFormatException nfe) {
                 throw new BuildException("Invalid 'idle' attribute (must be an integer): [" + idle + "]",  nfe);
             }
diff --git a/java/org/apache/catalina/manager/ManagerServlet.java b/java/org/apache/catalina/manager/ManagerServlet.java
index 953b5f6a6c..0c55535fa4 100644
--- a/java/org/apache/catalina/manager/ManagerServlet.java
+++ b/java/org/apache/catalina/manager/ManagerServlet.java
@@ -1288,7 +1288,7 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet {
             int expired = 0;
             for (Session session : sessions) {
                 int time = (int) (session.getIdleTimeInternal() / 1000L);
-                if (idle >= 0 && time >= idle * 60) {
+                if (idle >= 0 && time >= (long) idle * 60) {
                     session.expire();
                     expired++;
                 }


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


(tomcat) 08/14: Register the missing serverinfo Ant task in antlib.xml and catalina.tasks

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit aacb2cd4d76b0bc1f0c86c4de3d10bec67d9509c
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:16:34 2026 +0200

    Register the missing serverinfo Ant task in antlib.xml and catalina.tasks
---
 java/org/apache/catalina/ant/antlib.xml     | 3 +++
 java/org/apache/catalina/ant/catalina.tasks | 1 +
 2 files changed, 4 insertions(+)

diff --git a/java/org/apache/catalina/ant/antlib.xml b/java/org/apache/catalina/ant/antlib.xml
index 787c4fabcd..1cdafcaee5 100644
--- a/java/org/apache/catalina/ant/antlib.xml
+++ b/java/org/apache/catalina/ant/antlib.xml
@@ -53,6 +53,9 @@
   <typedef
         name="sslConnectorCiphers"
         classname="org.apache.catalina.ant.SslConnectorCiphersTask" />
+  <typedef
+        name="serverinfo"
+        classname="org.apache.catalina.ant.ServerinfoTask" />
   <!-- Jk Task -->
   <typedef
         name="jkupdate"
diff --git a/java/org/apache/catalina/ant/catalina.tasks b/java/org/apache/catalina/ant/catalina.tasks
index eb901ed3fd..4484f5aed3 100644
--- a/java/org/apache/catalina/ant/catalina.tasks
+++ b/java/org/apache/catalina/ant/catalina.tasks
@@ -27,6 +27,7 @@ findleaks=org.apache.catalina.ant.FindLeaksTask
 vminfo=org.apache.catalina.ant.VminfoTask
 threaddump=org.apache.catalina.ant.ThreaddumpTask
 sslConnectorCiphers=org.apache.catalina.ant.SslConnectorCiphersTask
+serverinfo=org.apache.catalina.ant.ServerinfoTask
 
 #Jk Task
 jkupdate=org.apache.catalina.ant.JKStatusUpdateTask


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


(tomcat) 11/14: Fail with a clear BuildException when a JMX string-to-type conversion is impossible instead of sending the raw String to the server

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 2bc2bc5c136f00e4a3bdd7c4ba4c1185e6e41f04
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:28:23 2026 +0200

    Fail with a clear BuildException when a JMX string-to-type conversion is impossible instead of sending the raw String to the server
---
 .../catalina/ant/jmx/JMXAccessorSetTask.java       |  4 ++
 .../apache/catalina/ant/jmx/JMXAccessorTask.java   | 46 +++++++++-------------
 .../catalina/ant/jmx/TestJMXAccessorTask.java      | 45 +++++++++++++++++++++
 3 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java b/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java
index 96f1bae2f5..2d69b1fd8b 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java
@@ -179,6 +179,10 @@ public class JMXAccessorSetTask extends JMXAccessorTask {
         } else {
             if (isConvert()) {
                 String mType = getMBeanAttributeType(jmxServerConnection, name, attribute);
+                if (mType == null) {
+                    throw new BuildException(
+                            "Attribute '" + attribute + "' not found on MBean '" + name + "' for set");
+                }
                 realValue = convertStringToType(value, mType);
             } else {
                 realValue = value;
diff --git a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
index 4a80078fde..5e7dd9884f 100644
--- a/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
+++ b/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java
@@ -610,65 +610,57 @@ public class JMXAccessorTask extends BaseRedirectorHelperTask {
      * @param valueType The type
      *
      * @return The converted object
+     *
+     * @throws BuildException The value cannot be converted to the requested type, or the type is not supported
      */
     protected Object convertStringToType(String value, String valueType) {
         if ("java.lang.String".equals(valueType)) {
             return value;
         }
+        if (valueType == null) {
+            throw new BuildException("Unable to convert value '" + value + "': no target type available");
+        }
 
-        Object convertValue = value;
         if ("java.lang.Integer".equals(valueType) || "int".equals(valueType)) {
             try {
-                convertValue = Integer.valueOf(value);
+                return Integer.valueOf(value);
             } catch (NumberFormatException ex) {
-                if (isEcho()) {
-                    handleErrorOutput("Unable to convert to integer:" + value);
-                }
+                throw new BuildException("Unable to convert to integer:" + value, ex);
             }
         } else if ("java.lang.Long".equals(valueType) || "long".equals(valueType)) {
             try {
-                convertValue = Long.valueOf(value);
+                return Long.valueOf(value);
             } catch (NumberFormatException ex) {
-                if (isEcho()) {
-                    handleErrorOutput("Unable to convert to long:" + value);
-                }
+                throw new BuildException("Unable to convert to long:" + value, ex);
             }
         } else if ("java.lang.Boolean".equals(valueType) || "boolean".equals(valueType)) {
-            convertValue = Boolean.valueOf(value);
+            return Boolean.valueOf(value);
         } else if ("java.lang.Float".equals(valueType) || "float".equals(valueType)) {
             try {
-                convertValue = Float.valueOf(value);
+                return Float.valueOf(value);
             } catch (NumberFormatException ex) {
-                if (isEcho()) {
-                    handleErrorOutput("Unable to convert to float:" + value);
-                }
+                throw new BuildException("Unable to convert to float:" + value, ex);
             }
         } else if ("java.lang.Double".equals(valueType) || "double".equals(valueType)) {
             try {
-                convertValue = Double.valueOf(value);
+                return Double.valueOf(value);
             } catch (NumberFormatException ex) {
-                if (isEcho()) {
-                    handleErrorOutput("Unable to convert to double:" + value);
-                }
+                throw new BuildException("Unable to convert to double:" + value, ex);
             }
         } else if ("javax.management.ObjectName".equals(valueType) || "name".equals(valueType)) {
             try {
-                convertValue = new ObjectName(value);
+                return new ObjectName(value);
             } catch (MalformedObjectNameException e) {
-                if (isEcho()) {
-                    handleErrorOutput("Unable to convert to ObjectName:" + value);
-                }
+                throw new BuildException("Unable to convert to ObjectName:" + value, e);
             }
         } else if ("java.net.InetAddress".equals(valueType)) {
             try {
-                convertValue = InetAddress.getByName(value);
+                return InetAddress.getByName(value);
             } catch (UnknownHostException exc) {
-                if (isEcho()) {
-                    handleErrorOutput("Unable to resolve host name:" + value);
-                }
+                throw new BuildException("Unable to resolve host name:" + value, exc);
             }
         }
-        return convertValue;
+        throw new BuildException("Unsupported conversion type '" + valueType + "' for value '" + value + "'");
     }
 
     /**
diff --git a/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java b/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java
index 3531a52ac6..b7104604d7 100644
--- a/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java
+++ b/test/org/apache/catalina/ant/jmx/TestJMXAccessorTask.java
@@ -27,6 +27,8 @@ import javax.management.openmbean.TabularType;
 import org.junit.Assert;
 import org.junit.Test;
 
+import org.apache.tools.ant.BuildException;
+
 public class TestJMXAccessorTask {
 
     @Test
@@ -44,6 +46,49 @@ public class TestJMXAccessorTask {
     }
 
 
+    @Test
+    public void testConvertStringToType() {
+        JMXAccessorTask task = new JMXAccessorTask();
+
+        Assert.assertEquals("x", task.convertStringToType("x", "java.lang.String"));
+        Assert.assertEquals(Integer.valueOf(7), task.convertStringToType("7", "int"));
+        Assert.assertEquals(Long.valueOf(7), task.convertStringToType("7", "java.lang.Long"));
+        Assert.assertEquals(Boolean.TRUE, task.convertStringToType("true", "boolean"));
+        Assert.assertEquals(Double.valueOf(1.5), task.convertStringToType("1.5", "double"));
+    }
+
+
+    @Test
+    public void testConvertStringToTypeInvalid() {
+        JMXAccessorTask task = new JMXAccessorTask();
+
+        assertConvertFails(task, "x", "int");
+        assertConvertFails(task, "x", "java.lang.Long");
+        assertConvertFails(task, "1.5", "java.lang.Integer");
+        assertConvertFails(task, "x", "javax.management.ObjectName");
+    }
+
+
+    @Test
+    public void testConvertStringToTypeUnsupportedType() {
+        JMXAccessorTask task = new JMXAccessorTask();
+
+        assertConvertFails(task, "x", "java.lang.Int");
+        assertConvertFails(task, "x", "java.util.List");
+        assertConvertFails(task, "x", null);
+    }
+
+
+    private static void assertConvertFails(JMXAccessorTask task, String value, String type) {
+        try {
+            task.convertStringToType(value, type);
+            Assert.fail("Expected a BuildException for value '" + value + "' and type '" + type + "'");
+        } catch (BuildException expected) {
+            // Expected
+        }
+    }
+
+
     private static TabularDataSupport createTabularData() throws OpenDataException {
         CompositeType detailsType = new CompositeType("details", "details", new String[] { "name" },
                 new String[] { "name" }, new OpenType<?>[] { SimpleType.STRING });


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


(tomcat) 01/14: Fix FindLeaksTask response constraint handling when statusLine is false

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c9e88e9481afef4e7cc21c4aab98a8bb7da918d9
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 18:05:49 2026 +0200

    Fix FindLeaksTask response constraint handling when statusLine is false
    
    With statusLine=false the Manager response contains only leaked
    context paths, which the inherited "OK -" first-line constraint
    treated as an error, inverting success and failure. Ignore the
    response constraint internally for that mode.
---
 java/org/apache/catalina/ant/FindLeaksTask.java | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/java/org/apache/catalina/ant/FindLeaksTask.java b/java/org/apache/catalina/ant/FindLeaksTask.java
index 3428816326..bd9ae4dbc2 100644
--- a/java/org/apache/catalina/ant/FindLeaksTask.java
+++ b/java/org/apache/catalina/ant/FindLeaksTask.java
@@ -58,6 +58,9 @@ public class FindLeaksTask extends AbstractCatalinaTask {
     @Override
     public void execute() throws BuildException {
         super.execute();
+        if (!statusLine) {
+            setIgnoreResponseConstraint(true);
+        }
         execute("/findleaks?statusLine=" + Boolean.toString(statusLine));
     }
 }


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


(tomcat) 05/14: Align default URL-encoding charset of the Manager Ant tasks with the server default of UTF-8

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 27e28fc0a59efac3c8622d2902ec5733a88759f9
Author: opencode <re...@apache.org>
AuthorDate: Tue Sep 29 19:09:16 2026 +0200

    Align default URL-encoding charset of the Manager Ant tasks with the server default of UTF-8
---
 java/org/apache/catalina/ant/AbstractCatalinaTask.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/ant/AbstractCatalinaTask.java b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
index bf20a8ae35..fb5b9138e9 100644
--- a/java/org/apache/catalina/ant/AbstractCatalinaTask.java
+++ b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
@@ -51,7 +51,7 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
     /**
      * The charset used during URL encoding.
      */
-    protected String charset = "ISO-8859-1";
+    protected String charset = "UTF-8";
 
     /**
      * Returns the charset used during URL encoding.


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