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
The following commit(s) were added to refs/heads/9.0.x by this push:
new 2cd751161d Minor fixes from code review
2cd751161d is described below
commit 2cd751161da4ae512f9039a445a25764c42e1001
Author: remm <[email protected]>
AuthorDate: Thu Jun 25 21:49:02 2026 +0200
Minor fixes from code review
---
java/org/apache/catalina/Pipeline.java | 2 +-
.../apache/catalina/manager/util/SessionUtils.java | 11 +++--
.../org/apache/catalina/mbeans/ClassNameMBean.java | 7 ++-
.../org/apache/catalina/mbeans/ConnectorMBean.java | 8 ++-
.../org/apache/catalina/mbeans/ContainerMBean.java | 11 +++--
.../catalina/mbeans/ContextEnvironmentMBean.java | 6 ++-
.../catalina/mbeans/ContextResourceLinkMBean.java | 8 +--
.../catalina/mbeans/ContextResourceMBean.java | 8 +--
.../mbeans/GlobalResourcesLifecycleListener.java | 57 +++++++++++++++++++++-
.../apache/catalina/mbeans/LocalStrings.properties | 6 +++
java/org/apache/catalina/mbeans/MBeanFactory.java | 6 +++
java/org/apache/catalina/realm/CombinedRealm.java | 12 +++--
.../org/apache/catalina/realm/DataSourceRealm.java | 19 +++++++-
.../apache/catalina/realm/LocalStrings.properties | 4 ++
14 files changed, 139 insertions(+), 26 deletions(-)
diff --git a/java/org/apache/catalina/Pipeline.java
b/java/org/apache/catalina/Pipeline.java
index 2098778d66..d3e66f13f3 100644
--- a/java/org/apache/catalina/Pipeline.java
+++ b/java/org/apache/catalina/Pipeline.java
@@ -23,7 +23,7 @@ import java.util.Set;
* is invoked. It is required that a Valve somewhere in the pipeline (usually
the last one) must process the request and
* create the corresponding response, rather than trying to pass the request
on.
* <p>
- * There is generally a single Pipeline instance associated with each
Container. The container's normal request
+ * There is a single Pipeline instance associated with each Container. The
container's normal request
* processing functionality is generally encapsulated in a container-specific
Valve, which should always be executed at
* the end of a pipeline. To facilitate this, the <code>setBasic()</code>
method is provided to set the Valve instance
* that will always be executed last. Other Valves will be executed in the
order that they were added, before the basic
diff --git a/java/org/apache/catalina/manager/util/SessionUtils.java
b/java/org/apache/catalina/manager/util/SessionUtils.java
index ebb5538d75..da47ac322a 100644
--- a/java/org/apache/catalina/manager/util/SessionUtils.java
+++ b/java/org/apache/catalina/manager/util/SessionUtils.java
@@ -60,22 +60,23 @@ public class SessionUtils {
new String[] { "Login", "User", "userName", "UserName",
"Utilisateur", "SPRING_SECURITY_LAST_USERNAME" };
/**
- * Try to get user locale from the session, if possible. IMPLEMENTATION
NOTE: this method has explicit support for
- * Tapestry 3, Struts 1.x and Spring JSF check the browser meta tag
"accept languages" to choose what language to
- * display.
+ * Try to get user locale from the session, if possible.
*
* @param in_session The session
*
- * @return the locale
+ * @return the locale, or {@code null} if it cannot be determined
*/
public static Locale guessLocaleFromSession(final Session in_session) {
return guessLocaleFromSession(in_session.getSession());
}
/**
- * Try to get user locale from the HttpSession, if possible.
+ * Try to get user locale from the session, if possible. Searches for
Locale objects stored under known attribute
+ * names used by common frameworks (Struts, JSTL, Spring MVC), and falls
back to iterating all session attributes if
+ * exactly one Locale is found.
*
* @param in_session The HTTP session
+ *
* @return the locale, or {@code null} if it cannot be determined
*/
public static Locale guessLocaleFromSession(final HttpSession in_session) {
diff --git a/java/org/apache/catalina/mbeans/ClassNameMBean.java
b/java/org/apache/catalina/mbeans/ClassNameMBean.java
index 440f0d1880..c1f46c52e0 100644
--- a/java/org/apache/catalina/mbeans/ClassNameMBean.java
+++ b/java/org/apache/catalina/mbeans/ClassNameMBean.java
@@ -38,6 +38,11 @@ public class ClassNameMBean<T> extends BaseCatalinaMBean<T> {
@Override
public String getClassName() {
- return this.resource.getClass().getName();
+ Object resource = this.resource;
+ if (resource != null) {
+ return resource.getClass().getName();
+ } else {
+ return null;
+ }
}
}
diff --git a/java/org/apache/catalina/mbeans/ConnectorMBean.java
b/java/org/apache/catalina/mbeans/ConnectorMBean.java
index 4189694176..1bdd2a8473 100644
--- a/java/org/apache/catalina/mbeans/ConnectorMBean.java
+++ b/java/org/apache/catalina/mbeans/ConnectorMBean.java
@@ -27,7 +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.coyote.tomcat5.CoyoteConnector</code>
+ * A <strong>ModelMBean</strong> implementation for the
<code>org.apache.catalina.connector.Connector</code>
* component.
*/
public class ConnectorMBean extends ClassNameMBean<Connector> {
@@ -72,6 +72,10 @@ public class ConnectorMBean extends
ClassNameMBean<Connector> {
}
Connector connector = doGetManagedResource();
- IntrospectionUtils.setProperty(connector, name, String.valueOf(value));
+ if (value == null) {
+ IntrospectionUtils.setProperty(connector, name, null);
+ } else {
+ IntrospectionUtils.setProperty(connector, name,
String.valueOf(value));
+ }
}
}
diff --git a/java/org/apache/catalina/mbeans/ContainerMBean.java
b/java/org/apache/catalina/mbeans/ContainerMBean.java
index 35f9b6b1d2..0e900a9c4e 100644
--- a/java/org/apache/catalina/mbeans/ContainerMBean.java
+++ b/java/org/apache/catalina/mbeans/ContainerMBean.java
@@ -75,14 +75,19 @@ public class ContainerMBean extends
BaseCatalinaMBean<ContainerBase> {
oldValue = container.getStartChildren();
container.setStartChildren(false);
container.addChild(contained);
- contained.init();
- } catch (LifecycleException e) {
- throw new MBeanException(e);
} finally {
if (container != null) {
container.setStartChildren(oldValue);
}
}
+
+ try {
+ contained.init();
+ } catch (LifecycleException e) {
+ // If init fails, try to cleanup since the MBean may not have been
added
+ container.removeChild(contained);
+ throw new MBeanException(e);
+ }
}
diff --git a/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
b/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
index 8a7ce9e07a..973029c9cd 100644
--- a/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java
@@ -47,7 +47,9 @@ public class ContextEnvironmentMBean extends
BaseCatalinaMBean<ContextEnvironmen
// cannot use side effects. It's removed and added back each time
// there is a modification in a resource.
NamingResources nr = ce.getNamingResources();
- nr.removeEnvironment(ce.getName());
- nr.addEnvironment(ce);
+ if (nr != null) {
+ nr.removeEnvironment(ce.getName());
+ nr.addEnvironment(ce);
+ }
}
}
diff --git a/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
b/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
index 445c9bdf3f..fedca7e156 100644
--- a/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java
@@ -103,13 +103,15 @@ public class ContextResourceLinkMBean extends
BaseCatalinaMBean<ContextResourceL
} else if ("type".equals(name)) {
crl.setType((String) value);
} else {
- crl.setProperty(name, "" + value);
+ crl.setProperty(name, value == null ? null : value.toString());
}
// cannot use side effects. It's removed and added back each time
// there is a modification in a resource.
NamingResources nr = crl.getNamingResources();
- nr.removeResourceLink(crl.getName());
- nr.addResourceLink(crl);
+ if (nr != null) {
+ nr.removeResourceLink(crl.getName());
+ nr.addResourceLink(crl);
+ }
}
}
diff --git a/java/org/apache/catalina/mbeans/ContextResourceMBean.java
b/java/org/apache/catalina/mbeans/ContextResourceMBean.java
index 968cc160cb..6990edc062 100644
--- a/java/org/apache/catalina/mbeans/ContextResourceMBean.java
+++ b/java/org/apache/catalina/mbeans/ContextResourceMBean.java
@@ -106,13 +106,15 @@ public class ContextResourceMBean extends
BaseCatalinaMBean<ContextResource> {
} else if ("type".equals(name)) {
cr.setType((String) value);
} else {
- cr.setProperty(name, "" + value);
+ cr.setProperty(name, value == null ? null : value.toString());
}
// cannot use side effects. It's removed and added back each time
// there is a modification in a resource.
NamingResources nr = cr.getNamingResources();
- nr.removeResource(cr.getName());
- nr.addResource(cr);
+ if (nr != null) {
+ nr.removeResource(cr.getName());
+ nr.addResource(cr);
+ }
}
}
diff --git
a/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java
b/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java
index 16bc43fc30..dd8a94adf0 100644
--- a/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java
+++ b/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java
@@ -238,6 +238,61 @@ public class GlobalResourcesLifecycleListener implements
LifecycleListener {
if (log.isTraceEnabled()) {
log.trace("Destroying MBeans for Global JNDI Resources");
}
- // FIXME: Implement removing MBeans
+ // Look up our global naming context
+ Context context;
+ try {
+ context = (Context) (new InitialContext()).lookup("java:/");
+ } catch (NamingException e) {
+ log.error(sm.getString("globalResources.noNamingContext"));
+ return;
+ }
+
+ // Recurse through the defined global JNDI resources context
+ try {
+ destroyMBeans("", context);
+ } catch (NamingException e) {
+ log.error(sm.getString("globalResources.destroyError"), e);
+ }
+ }
+
+
+ /**
+ * Destroy the MBeans for the interesting global JNDI resources in the
specified naming context.
+ *
+ * @param prefix Prefix for complete object name paths
+ * @param context Context to be scanned
+ *
+ * @exception NamingException if a JNDI exception occurs
+ */
+ protected void destroyMBeans(String prefix, Context context) throws
NamingException {
+
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("globalResources.destroy", prefix));
+ }
+
+ try {
+ NamingEnumeration<Binding> bindings = context.listBindings("");
+ while (bindings.hasMore()) {
+ Binding binding = bindings.next();
+ String name = prefix + binding.getName();
+ Object value = context.lookup(binding.getName());
+ if (log.isTraceEnabled()) {
+ log.trace("Checking resource " + name);
+ }
+ if (value instanceof Context) {
+ destroyMBeans(name + "/", (Context) value);
+ } else if (value instanceof UserDatabase) {
+ try {
+ MBeanUtils.destroyMBeanUserDatabase(name);
+ } catch (Exception e) {
+
log.error(sm.getString("globalResources.userDatabaseDestroyError", name), e);
+ }
+ }
+ }
+ } catch (RuntimeException ex) {
+ log.error(sm.getString("globalResources.destroyError.runtime"),
ex);
+ } catch (OperationNotSupportedException ex) {
+ log.error(sm.getString("globalResources.destroyError.operation"),
ex);
+ }
}
}
diff --git a/java/org/apache/catalina/mbeans/LocalStrings.properties
b/java/org/apache/catalina/mbeans/LocalStrings.properties
index 16d8b7fe41..5dc6a1311f 100644
--- a/java/org/apache/catalina/mbeans/LocalStrings.properties
+++ b/java/org/apache/catalina/mbeans/LocalStrings.properties
@@ -24,8 +24,13 @@ globalResources.createError.userDatabase=Cannot create
UserDatabase MBean for re
globalResources.createError.userDatabase.group=Cannot create Group MBean for
group [{0}]
globalResources.createError.userDatabase.role=Cannot create Role MBean for
role [{0}]
globalResources.createError.userDatabase.user=Cannot create User MBean for
user [{0}]
+globalResources.destroy=Destroying MBeans for Global JNDI Resources in Context
[{0}]
+globalResources.destroyError=Exception processing global JNDI Resources
+globalResources.destroyError.operation=Operation not supported error
destroying MBeans
+globalResources.destroyError.runtime=Unexpected error destroying MBeans
globalResources.noNamingContext=No global naming context defined for server
globalResources.userDatabaseCreateError=Exception creating UserDatabase MBeans
for [{0}]
+globalResources.userDatabaseDestroyError=Exception destroying UserDatabase
MBeans for [{0}]
listener.notServer=This listener must only be nested within Server elements,
but is in [{0}].
@@ -41,6 +46,7 @@ mBeanFactory.contextDestroyError=Error during context [{0}]
destroy
mBeanFactory.contextRemove.addServicedFail=Unable to remove context [{0}] as
another component is currently servicing that context
mBeanFactory.managerContext=Manager components may only be added to Contexts.
mBeanFactory.noDeployer=Deployer not found for host [{0}]
+mBeanFactory.noHost=No host found with object name [{0}]
mBeanFactory.noParent=No parent found with object name [{0}]
mBeanFactory.noService=Service with the domain [{0}] was not found
mBeanFactory.notServer=The container is not a Server
diff --git a/java/org/apache/catalina/mbeans/MBeanFactory.java
b/java/org/apache/catalina/mbeans/MBeanFactory.java
index 96f5a1ac9c..f5e27a86e2 100644
--- a/java/org/apache/catalina/mbeans/MBeanFactory.java
+++ b/java/org/apache/catalina/mbeans/MBeanFactory.java
@@ -472,6 +472,9 @@ public class MBeanFactory {
Service service = getService(pname);
Engine engine = service.getContainer();
Host host = (Host) engine.findChild(pname.getKeyProperty("host"));
+ if (host == null) {
+ throw new
IllegalArgumentException(sm.getString("mBeanFactory.noHost",
pname.getKeyProperty("host")));
+ }
host.addChild(context);
}
@@ -750,6 +753,9 @@ public class MBeanFactory {
} else {
log.warn(sm.getString("mBeanFactory.noDeployer", hostName));
Host host = (Host) engine.findChild(hostName);
+ if (host == null) {
+ throw new
IllegalArgumentException(sm.getString("mBeanFactory.noHost", hostName));
+ }
Context context = (Context) host.findChild(pathStr);
// Remove this component from its parent component
host.removeChild(context);
diff --git a/java/org/apache/catalina/realm/CombinedRealm.java
b/java/org/apache/catalina/realm/CombinedRealm.java
index d810de8758..30b9fc5204 100644
--- a/java/org/apache/catalina/realm/CombinedRealm.java
+++ b/java/org/apache/catalina/realm/CombinedRealm.java
@@ -75,15 +75,18 @@ public class CombinedRealm extends RealmBase {
/**
* Returns the JMX ObjectNames of the realms that this realm is wrapping.
+ * Entries for realms that do not implement LifecycleMBeanBase will be
null.
*
- * @return the array of realm ObjectNames
+ * @return the array of realm ObjectNames, which may contain null entries
*/
public ObjectName[] getRealms() {
ObjectName[] result = new ObjectName[realms.size()];
+ int i = 0;
for (Realm realm : realms) {
if (realm instanceof LifecycleMBeanBase) {
- result[realms.indexOf(realm)] = ((LifecycleMBeanBase)
realm).getObjectName();
+ result[i] = ((LifecycleMBeanBase) realm).getObjectName();
}
+ i++;
}
return result;
}
@@ -181,14 +184,15 @@ public class CombinedRealm extends RealmBase {
@Override
public void setContainer(Container container) {
+ int i = 0;
for (Realm realm : realms) {
// Set the realmPath for JMX naming
if (realm instanceof RealmBase) {
- ((RealmBase) realm).setRealmPath(getRealmPath() + "/realm" +
realms.indexOf(realm));
+ ((RealmBase) realm).setRealmPath(getRealmPath() + "/realm" +
Integer.toString(i));
}
-
// Set the container for sub-realms. Mainly so logging works.
realm.setContainer(container);
+ i++;
}
super.setContainer(container);
}
diff --git a/java/org/apache/catalina/realm/DataSourceRealm.java
b/java/org/apache/catalina/realm/DataSourceRealm.java
index 47e049f5c0..bfa4572dc0 100644
--- a/java/org/apache/catalina/realm/DataSourceRealm.java
+++ b/java/org/apache/catalina/realm/DataSourceRealm.java
@@ -523,7 +523,7 @@ public class DataSourceRealm extends RealmBase {
private boolean isRoleStoreDefined() {
- return userRoleTable != null || roleNameCol != null;
+ return (userRoleTable != null && !userRoleTable.isEmpty()) &&
(roleNameCol != null && !roleNameCol.isEmpty());
}
@@ -532,6 +532,23 @@ public class DataSourceRealm extends RealmBase {
@Override
protected void startInternal() throws LifecycleException {
+ if (userTable == null || userTable.isEmpty()) {
+ throw new
LifecycleException(sm.getString("dataSourceRealm.noUserTable"));
+ }
+ if (userNameCol == null || userNameCol.isEmpty()) {
+ throw new
LifecycleException(sm.getString("dataSourceRealm.noUserNameCol"));
+ }
+ if (userCredCol == null || userCredCol.isEmpty()) {
+ throw new
LifecycleException(sm.getString("dataSourceRealm.noUserCredCol"));
+ }
+
+ // Validate role configuration: either both must be set or neither
+ boolean hasRoleTable = userRoleTable != null &&
!userRoleTable.isEmpty();
+ boolean hasRoleNameCol = roleNameCol != null && !roleNameCol.isEmpty();
+ if (hasRoleTable != hasRoleNameCol) {
+ throw new
LifecycleException(sm.getString("dataSourceRealm.roleConfigMismatch"));
+ }
+
// Create the roles PreparedStatement string
StringBuilder temp = new StringBuilder("SELECT ");
temp.append(roleNameCol);
diff --git a/java/org/apache/catalina/realm/LocalStrings.properties
b/java/org/apache/catalina/realm/LocalStrings.properties
index f8b55989f3..114ed3c81a 100644
--- a/java/org/apache/catalina/realm/LocalStrings.properties
+++ b/java/org/apache/catalina/realm/LocalStrings.properties
@@ -36,6 +36,10 @@ dataSourceRealm.exception=Exception performing authentication
dataSourceRealm.getPassword.exception=Exception retrieving password for [{0}]
dataSourceRealm.getRoles.exception=Exception retrieving roles for [{0}]
dataSourceRealm.noNamingContext=Cannot access the server to retrieve the
naming context
+dataSourceRealm.noUserTable=No user table was specified
+dataSourceRealm.noUserNameCol=No column was specified for user names
+dataSourceRealm.noUserCredCol=No column was specified for user credentials
+dataSourceRealm.roleConfigMismatch=Role configuration is incomplete: both
userRoleTable and roleNameCol must be specified together
jaasCallback.username=Returned username [{0}]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]