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 19:02:43 UTC
(tomcat) branch 9.0.x updated (ab60dfaaef -> 751734ac01)
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a change to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
from ab60dfaaef Avoid very rare race between async write notification and completion
new 5ebe831c54 Fix FindLeaksTask response constraint handling when statusLine is false
new 6d02846dde Remove unused internalid attribute from JKStatusUpdateTask
new 4662db1943 Add configurable timeout for HTTP connections used by the Manager Ant tasks
new fa5dca44b0 Avoid buffering remote WAR uploads of unknown length in memory in the Manager Ant tasks
new 2fb1b581c4 Align default URL-encoding charset of the Manager Ant tasks with the server default of UTF-8
new cdd2d17ae4 Include the HTTP error response body in the error messages of the Manager Ant tasks
new 4dfae023d6 Prevent oversized 'idle' values from expiring all sessions via integer overflow in the sessions/expire command
new 48db451d71 Register the missing serverinfo Ant task in antlib.xml and catalina.tasks
new 5b761d1c86 Close the JMX connection owned by a task or condition when no reference is used to share it
new 15da47e510 Fail with a clear BuildException when a JMX string-to-type conversion is impossible instead of sending the raw String to the server
new f1dae0cb99 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 1ac7c47cc9 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 751734ac01 Log the error message returned by a JMX task when failOnError is false instead of discarding it
The 13 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/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 +++++++++++
14 files changed, 504 insertions(+), 119 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) 01/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 5ebe831c5469c1952cdcbe34fb472a7cc28708fa
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) 02/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 6d02846ddeb6a2d1ddecc866f9f8688205aebf90
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) 10/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 15da47e51052420d284f105897c933f03f783897
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 5ec41eb5dc..bcefcda81f 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) 03/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4662db1943e81c84f086918c7a53a7dd1600e81e
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 52d538fd73..664c6f9843 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.
*/
@@ -230,6 +256,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);
+ }
if (istream != null) {
preAuthenticate();
@@ -354,6 +384,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.setRequestMethod(Method.OPTIONS);
hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0");
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) 05/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 2fb1b581c4c3e47c5331e6f671af2ae83ef3f932
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 96b35ed4e9..328a856d0c 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
(tomcat) 12/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 1ac7c47cc9c4f4bf13bcf6d15f50ef08678fcde0
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 bcefcda81f..7f2a40261b 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) 09/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 5b761d1c86f2d7842dd5e08727c15e316b0920a7
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 ebbe610bc8..5ec41eb5dc 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) 11/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit f1dae0cb9919b1ac943779bb89c03d0426190313
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) 06/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit cdd2d17ae4a32a8794c337c3a47c05a8befd4f72
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 328a856d0c..40176a0073 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;
@@ -299,6 +300,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/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4dfae023d62f5223c1e7845e253b0e755788db36
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 d77a46ebe7..6c54a4b21e 100644
--- a/java/org/apache/catalina/manager/ManagerServlet.java
+++ b/java/org/apache/catalina/manager/ManagerServlet.java
@@ -1307,7 +1307,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) 13/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 751734ac01d49906c73e8d8c7afa41cefcc53492
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 7f2a40261b..4069887b45 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) 04/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit fa5dca44b0a06dc01f6b88ec9ac5a7c47faa0a56
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 664c6f9843..96b35ed4e9 100644
--- a/java/org/apache/catalina/ant/AbstractCatalinaTask.java
+++ b/java/org/apache/catalina/ant/AbstractCatalinaTask.java
@@ -272,6 +272,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) 08/13: 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 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 48db451d71334fb3a3d394a215a075286672c750
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