This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 92cb4c500a Follow up to "Keep naming resource entries consistent when
updated..."
92cb4c500a is described below
commit 92cb4c500abd975a587cc18c0696b20f1a275b9a
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Oct 8 15:08:47 2026 +0100
Follow up to "Keep naming resource entries consistent when updated..."
- consistent validation of new attribute
- align MBean with ContextEnvironment
- improve roll-back
- format code
---
.../apache/catalina/mbeans/BaseCatalinaMBean.java | 3 +
.../catalina/mbeans/BaseNamingResourceMBean.java | 78 ++++++++++++++++++++++
.../org/apache/catalina/mbeans/ConnectorMBean.java | 3 +-
.../org/apache/catalina/mbeans/ContainerMBean.java | 7 +-
.../catalina/mbeans/ContextEnvironmentMBean.java | 54 ++++++++++-----
java/org/apache/catalina/mbeans/ContextMBean.java | 3 +-
.../catalina/mbeans/ContextResourceLinkMBean.java | 26 ++++----
.../catalina/mbeans/ContextResourceMBean.java | 41 +++++++-----
.../mbeans/DataSourceUserDatabaseMBean.java | 2 +-
.../apache/catalina/mbeans/LocalStrings.properties | 2 +
java/org/apache/catalina/mbeans/MBeanDumper.java | 1 +
java/org/apache/catalina/mbeans/MBeanUtils.java | 4 +-
java/org/apache/catalina/mbeans/ServiceMBean.java | 4 +-
13 files changed, 167 insertions(+), 61 deletions(-)
diff --git a/java/org/apache/catalina/mbeans/BaseCatalinaMBean.java
b/java/org/apache/catalina/mbeans/BaseCatalinaMBean.java
index f5ac3f28fa..f91652b592 100644
--- a/java/org/apache/catalina/mbeans/BaseCatalinaMBean.java
+++ b/java/org/apache/catalina/mbeans/BaseCatalinaMBean.java
@@ -40,6 +40,7 @@ public abstract class BaseCatalinaMBean<T> extends
BaseModelMBean {
* Returns the managed resource associated with this MBean.
*
* @return the managed resource
+ *
* @throws MBeanException if the resource cannot be retrieved
*/
protected T doGetManagedResource() throws MBeanException {
@@ -57,7 +58,9 @@ public abstract class BaseCatalinaMBean<T> extends
BaseModelMBean {
* Creates a new instance of the specified class.
*
* @param type the fully qualified class name
+ *
* @return the new instance
+ *
* @throws MBeanException if the instance cannot be created
*/
protected static Object newInstance(String type) throws MBeanException {
diff --git a/java/org/apache/catalina/mbeans/BaseNamingResourceMBean.java
b/java/org/apache/catalina/mbeans/BaseNamingResourceMBean.java
new file mode 100644
index 0000000000..16320e743a
--- /dev/null
+++ b/java/org/apache/catalina/mbeans/BaseNamingResourceMBean.java
@@ -0,0 +1,78 @@
+/*
+ * 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.mbeans;
+
+import javax.management.Attribute;
+import javax.management.RuntimeOperationsException;
+
+import org.apache.juli.logging.Log;
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * Abstract base class for Naming Resource MBeans.
+ *
+ * @param <T> the type of the managed resource
+ */
+public abstract class BaseNamingResourceMBean<T> extends BaseCatalinaMBean<T> {
+
+ private static final StringManager sm =
StringManager.getManager(BaseNamingResourceMBean.class);
+
+
+ /**
+ * Validate the provided attribute. Checks include:
+ * <ul>
+ * <li>attribute is not null</li>
+ * <li>attribute name is not null</li>
+ * <li>attribute name is not "name"</li>
+ * </ul>
+ *
+ * @param attribute The attribute to validate
+ *
+ * @return {@code true} if the attribute is valid, {@code false} if the
caller should stop further processing.
+ */
+ protected boolean validateAttribute(Attribute attribute) {
+ // Validate the input parameters
+ if (attribute == null) {
+ throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullAttribute")),
+ sm.getString("mBean.nullAttribute"));
+ }
+
+ String name = attribute.getName();
+ if (name == null) {
+ throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullName")),
+ sm.getString("mBean.nullName"));
+ }
+
+ if ("name".equals(name)) {
+ // Updating the name actually needs removing and adding back the
+ // component under the new name. Ignore the change, as the other
+ // naming resource MBeans do.
+ getLog().info(sm.getString("mBean.nameChange"));
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Enables sub-classes to provide the correct logger for any log messages.
+ *
+ * @return The logger to use
+ */
+ protected abstract Log getLog();
+}
diff --git a/java/org/apache/catalina/mbeans/ConnectorMBean.java
b/java/org/apache/catalina/mbeans/ConnectorMBean.java
index 6205bd8148..8145a0f28b 100644
--- a/java/org/apache/catalina/mbeans/ConnectorMBean.java
+++ b/java/org/apache/catalina/mbeans/ConnectorMBean.java
@@ -27,8 +27,7 @@ import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
- * A <strong>ModelMBean</strong> implementation for the
<code>org.apache.catalina.connector.Connector</code>
- * component.
+ * A <strong>ModelMBean</strong> implementation for the
<code>org.apache.catalina.connector.Connector</code> component.
*/
public class ConnectorMBean extends ClassNameMBean<Connector> {
diff --git a/java/org/apache/catalina/mbeans/ContainerMBean.java
b/java/org/apache/catalina/mbeans/ContainerMBean.java
index 3466bb0a7e..aaf4c46b51 100644
--- a/java/org/apache/catalina/mbeans/ContainerMBean.java
+++ b/java/org/apache/catalina/mbeans/ContainerMBean.java
@@ -37,8 +37,8 @@ import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.startup.HostConfig;
/**
- * MBean wrapper for ContainerBase instances, providing JMX management
operations for child containers,
- * valves, and lifecycle listeners.
+ * MBean wrapper for ContainerBase instances, providing JMX management
operations for child containers, valves, and
+ * lifecycle listeners.
*/
public class ContainerMBean extends BaseCatalinaMBean<ContainerBase> {
/**
@@ -115,8 +115,7 @@ public class ContainerMBean extends
BaseCatalinaMBean<ContainerBase> {
*
* @param valveType ClassName of the valve to be added
*
- * @return the MBean name of the new valve, or null if the valve was not
- * added or has no registered MBean
+ * @return the MBean name of the new valve, or null if the valve was not
added or has no registered MBean
*
* @throws MBeanException if adding the valve failed
*/
diff --git a/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
b/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
index 02387a43dc..09c2372549 100644
--- a/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
@@ -20,10 +20,10 @@ import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanException;
import javax.management.ReflectionException;
-import javax.management.RuntimeOperationsException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
import org.apache.tomcat.util.descriptor.web.NamingResources;
import org.apache.tomcat.util.res.StringManager;
@@ -32,7 +32,11 @@ import org.apache.tomcat.util.res.StringManager;
* A <strong>ModelMBean</strong> implementation for the
* <code>org.apache.tomcat.util.descriptor.web.ContextEnvironment</code>
component.
*/
-public class ContextEnvironmentMBean extends
BaseCatalinaMBean<ContextEnvironment> {
+public class ContextEnvironmentMBean extends
BaseNamingResourceMBean<ContextEnvironment> {
+
+ private static final StringManager sm =
StringManager.getManager(ContextEnvironmentMBean.class);
+ private static final Log log =
LogFactory.getLog(ContextEnvironmentMBean.class);
+
/**
* Default constructor for ContextEnvironmentMBean.
@@ -40,31 +44,31 @@ public class ContextEnvironmentMBean extends
BaseCatalinaMBean<ContextEnvironmen
public ContextEnvironmentMBean() {
}
- private static final Log log =
LogFactory.getLog(ContextEnvironmentMBean.class);
- private static final StringManager sm =
StringManager.getManager(ContextEnvironmentMBean.class);
@Override
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException, MBeanException,
ReflectionException {
- if (attribute == null) {
- throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullAttribute")),
- sm.getString("mBean.nullAttribute"));
+ if (!validateAttribute(attribute)) {
+ return;
}
- ContextEnvironment ce = doGetManagedResource();
+ String name = attribute.getName();
+ Object value = attribute.getValue();
- if ("name".equals(attribute.getName())) {
- // Updating the name actually needs removing and adding back the
- // component under the new name. Ignore the change, as the other
- // naming resource MBeans do.
- log.info(sm.getString("mBean.nameChange"));
- return;
- }
+ ContextEnvironment ce = doGetManagedResource();
String oldType = ce.getType();
String oldValue = ce.getValue();
String oldLookup = ce.getLookupName();
+ String oldDescription = ce.getDescription();
+ boolean oldOverride = ce.getOverride();
+
+ // Entries with injection targets but no value are effectively ignored
+ if (ce.getInjectionTargets() != null &&
!ce.getInjectionTargets().isEmpty() && "value".equals(name) &&
+ (value == null || (value instanceof String s && s.isEmpty())))
{
+ throw new
IllegalArgumentException(sm.getString("contextEnvironment.ignore.injectionNoValue"));
+ }
super.setAttribute(attribute);
@@ -75,16 +79,30 @@ public class ContextEnvironmentMBean extends
BaseCatalinaMBean<ContextEnvironmen
try {
nr.removeEnvironment(ce.getName());
nr.addEnvironment(ce);
- } catch (IllegalArgumentException iae) {
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
// The change is not acceptable. Restore the previous state
// before passing the failure to the caller, so the entry is
// not lost.
ce.setType(oldType);
ce.setValue(oldValue);
ce.setLookupName(oldLookup);
- nr.addEnvironment(ce);
- throw iae;
+ ce.setDescription(oldDescription);
+ ce.setOverride(oldOverride);
+ try {
+ nr.addEnvironment(ce);
+ } catch (Throwable t1) {
+ ExceptionUtils.handleThrowable(t1);
+ t.addSuppressed(t1);
+ }
+ throw t;
}
}
}
+
+
+ @Override
+ protected Log getLog() {
+ return log;
+ }
}
diff --git a/java/org/apache/catalina/mbeans/ContextMBean.java
b/java/org/apache/catalina/mbeans/ContextMBean.java
index 23c27e1437..825a7ea552 100644
--- a/java/org/apache/catalina/mbeans/ContextMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextMBean.java
@@ -26,8 +26,7 @@ import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
/**
- * A <strong>ModelMBean</strong> implementation for the
- * <code>org.apache.catalina.Context</code> component.
+ * A <strong>ModelMBean</strong> implementation for the
<code>org.apache.catalina.Context</code> component.
*/
public class ContextMBean extends BaseCatalinaMBean<Context> {
diff --git a/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
b/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
index ee438d127e..743d58e8df 100644
--- a/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
@@ -32,7 +32,11 @@ import org.apache.tomcat.util.res.StringManager;
* A <strong>ModelMBean</strong> implementation for the
* <code>org.apache.tomcat.util.descriptor.web.ContextResourceLink</code>
component.
*/
-public class ContextResourceLinkMBean extends
BaseCatalinaMBean<ContextResourceLink> {
+public class ContextResourceLinkMBean extends
BaseNamingResourceMBean<ContextResourceLink> {
+
+ private static final Log log =
LogFactory.getLog(ContextResourceLinkMBean.class);
+ private static final StringManager sm =
StringManager.getManager(ContextResourceLinkMBean.class);
+
/**
* Default constructor for ContextResourceLinkMBean.
@@ -40,8 +44,6 @@ public class ContextResourceLinkMBean extends
BaseCatalinaMBean<ContextResourceL
public ContextResourceLinkMBean() {
}
- private static final Log log =
LogFactory.getLog(ContextResourceLinkMBean.class);
- private static final StringManager sm =
StringManager.getManager(ContextResourceLinkMBean.class);
@Override
public Object getAttribute(String name) throws AttributeNotFoundException,
MBeanException, ReflectionException {
@@ -80,26 +82,18 @@ public class ContextResourceLinkMBean extends
BaseCatalinaMBean<ContextResourceL
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException, MBeanException,
ReflectionException {
- // Validate the input parameters
- if (attribute == null) {
- throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullAttribute")),
- sm.getString("mBean.nullAttribute"));
+ if (!validateAttribute(attribute)) {
+ return;
}
String name = attribute.getName();
Object value = attribute.getValue();
- if (name == null) {
- throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullName")),
- sm.getString("mBean.nullName"));
- }
ContextResourceLink crl = doGetManagedResource();
switch (name) {
case "global" -> crl.setGlobal((String) value);
case "description" -> crl.setDescription((String) value);
- // Updating the name actually needs removing and adding back the
component under the new name
- case "name" -> log.info(sm.getString("mBean.nameChange"));
case "type" -> crl.setType((String) value);
default -> crl.setProperty(name, value == null ? null :
value.toString());
}
@@ -112,4 +106,10 @@ public class ContextResourceLinkMBean extends
BaseCatalinaMBean<ContextResourceL
nr.addResourceLink(crl);
}
}
+
+
+ @Override
+ protected Log getLog() {
+ return log;
+ }
}
diff --git a/java/org/apache/catalina/mbeans/ContextResourceMBean.java
b/java/org/apache/catalina/mbeans/ContextResourceMBean.java
index 669bc7726e..9919793e2c 100644
--- a/java/org/apache/catalina/mbeans/ContextResourceMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextResourceMBean.java
@@ -24,6 +24,7 @@ import javax.management.RuntimeOperationsException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.apache.tomcat.util.descriptor.web.NamingResources;
import org.apache.tomcat.util.res.StringManager;
@@ -32,7 +33,11 @@ import org.apache.tomcat.util.res.StringManager;
* A <strong>ModelMBean</strong> implementation for the
* <code>org.apache.tomcat.util.descriptor.web.ContextResource</code>
component.
*/
-public class ContextResourceMBean extends BaseCatalinaMBean<ContextResource> {
+public class ContextResourceMBean extends
BaseNamingResourceMBean<ContextResource> {
+
+ private static final Log log =
LogFactory.getLog(ContextResourceMBean.class);
+ private static final StringManager sm =
StringManager.getManager(ContextResourceMBean.class);
+
/**
* Default constructor for ContextResourceMBean.
@@ -40,8 +45,6 @@ public class ContextResourceMBean extends
BaseCatalinaMBean<ContextResource> {
public ContextResourceMBean() {
}
- private static final Log log =
LogFactory.getLog(ContextResourceMBean.class);
- private static final StringManager sm =
StringManager.getManager(ContextResourceMBean.class);
@Override
public Object getAttribute(String name) throws AttributeNotFoundException,
MBeanException, ReflectionException {
@@ -82,27 +85,19 @@ public class ContextResourceMBean extends
BaseCatalinaMBean<ContextResource> {
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException, MBeanException,
ReflectionException {
- // Validate the input parameters
- if (attribute == null) {
- throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullAttribute")),
- sm.getString("mBean.nullAttribute"));
+ if (!validateAttribute(attribute)) {
+ return;
}
+
String name = attribute.getName();
Object value = attribute.getValue();
- if (name == null) {
- throw new RuntimeOperationsException(new
IllegalArgumentException(sm.getString("mBean.nullName")),
- sm.getString("mBean.nullName"));
- }
ContextResource cr = doGetManagedResource();
-
String oldType = cr.getType();
switch (name) {
case "auth" -> cr.setAuth((String) value);
case "description" -> cr.setDescription((String) value);
- // Updating the name actually needs removing and adding back the
component under the new name
- case "name" -> log.info(sm.getString("mBean.nameChange"));
case "scope" -> cr.setScope((String) value);
case "type" -> cr.setType((String) value);
default -> cr.setProperty(name, value == null ? null :
value.toString());
@@ -115,14 +110,26 @@ public class ContextResourceMBean extends
BaseCatalinaMBean<ContextResource> {
try {
nr.removeResource(cr.getName());
nr.addResource(cr);
- } catch (IllegalArgumentException iae) {
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
// The change is not acceptable. Restore the previous type
// before passing the failure to the caller, so the entry is
// not lost.
cr.setType(oldType);
- nr.addResource(cr);
- throw iae;
+ try {
+ nr.addResource(cr);
+ } catch (Throwable t1) {
+ ExceptionUtils.handleThrowable(t1);
+ t.addSuppressed(t1);
+ }
+ throw t;
}
}
}
+
+
+ @Override
+ protected Log getLog() {
+ return log;
+ }
}
diff --git a/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java
b/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java
index 71e2d582da..e5ed2f16d4 100644
--- a/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java
+++ b/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java
@@ -115,7 +115,7 @@ public class DataSourceUserDatabaseMBean extends
BaseModelMBean {
/**
* Create a new Group and return the corresponding name.
*
- * @param groupname Group name of the new group
+ * @param groupname Group name of the new group
* @param description Description of the new group
*
* @return the new group name
diff --git a/java/org/apache/catalina/mbeans/LocalStrings.properties
b/java/org/apache/catalina/mbeans/LocalStrings.properties
index 9de716f0da..99697e075b 100644
--- a/java/org/apache/catalina/mbeans/LocalStrings.properties
+++ b/java/org/apache/catalina/mbeans/LocalStrings.properties
@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+contextEnvironment.ignore.injectionNoValue=Updates that set the value to null
or empty are ignored if there are injection targets defined
+
globalResources.create=Creating MBeans for Global JNDI Resources in Context
[{0}]
globalResources.createError=Exception processing global JNDI Resources
globalResources.createError.operation=Operation not supported error creating
MBeans
diff --git a/java/org/apache/catalina/mbeans/MBeanDumper.java
b/java/org/apache/catalina/mbeans/MBeanDumper.java
index 3230afffd9..bb213677c3 100644
--- a/java/org/apache/catalina/mbeans/MBeanDumper.java
+++ b/java/org/apache/catalina/mbeans/MBeanDumper.java
@@ -180,6 +180,7 @@ public class MBeanDumper {
* Escape a string value for display.
*
* @param value the value to escape
+ *
* @return the escaped value
*/
public static String escape(String value) {
diff --git a/java/org/apache/catalina/mbeans/MBeanUtils.java
b/java/org/apache/catalina/mbeans/MBeanUtils.java
index 9ef621e758..4f6a9f563c 100644
--- a/java/org/apache/catalina/mbeans/MBeanUtils.java
+++ b/java/org/apache/catalina/mbeans/MBeanUtils.java
@@ -489,8 +489,8 @@ public class MBeanUtils {
*/
static ObjectName createObjectName(String domain, User user) throws
MalformedObjectNameException {
- return new ObjectName(domain + ":type=User,username=" +
ObjectName.quote(user.getUsername()) +
- ",database=" +
ObjectName.quote(user.getUserDatabase().getId()));
+ return new ObjectName(domain + ":type=User,username=" +
ObjectName.quote(user.getUsername()) + ",database=" +
+ ObjectName.quote(user.getUserDatabase().getId()));
}
diff --git a/java/org/apache/catalina/mbeans/ServiceMBean.java
b/java/org/apache/catalina/mbeans/ServiceMBean.java
index 4fdff6a942..10172b9bba 100644
--- a/java/org/apache/catalina/mbeans/ServiceMBean.java
+++ b/java/org/apache/catalina/mbeans/ServiceMBean.java
@@ -23,8 +23,8 @@ import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
/**
- * JMX MBean wrapper for a {@link Service} instance. Provides operations to
- * add connectors and executors, and to query connectors and executors.
+ * JMX MBean wrapper for a {@link Service} instance. Provides operations to
add connectors and executors, and to query
+ * connectors and executors.
*/
public class ServiceMBean extends BaseCatalinaMBean<Service> {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]