This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 52ba355639 Minor fixes from code review
52ba355639 is described below
commit 52ba3556391467d0c3adf3bcde09f32382ec57b9
Author: remm <[email protected]>
AuthorDate: Mon Jun 22 15:44:27 2026 +0200
Minor fixes from code review
Most significant is the rework of the wrapper unload.
---
.../catalina/core/ApplicationDispatcher.java | 3 ---
.../catalina/core/ApplicationHttpRequest.java | 5 ++--
.../catalina/core/ApplicationHttpResponse.java | 2 +-
.../apache/catalina/core/ApplicationRequest.java | 2 +-
.../apache/catalina/core/ApplicationResponse.java | 2 +-
.../core/ApplicationServletRegistration.java | 1 +
.../org/apache/catalina/core/AsyncContextImpl.java | 2 +-
.../core/JreMemoryLeakPreventionListener.java | 2 +-
.../catalina/core/NamingContextListener.java | 15 ++++++-----
.../apache/catalina/core/StandardEngineValve.java | 3 +--
java/org/apache/catalina/core/StandardHost.java | 4 +--
.../org/apache/catalina/core/StandardPipeline.java | 1 +
.../core/StandardVirtualThreadExecutor.java | 5 +++-
java/org/apache/catalina/core/StandardWrapper.java | 14 ++++++----
.../catalina/core/StandardWrapperFacade.java | 4 +--
.../core/ThreadLocalLeakPreventionListener.java | 8 +++---
.../catalina/deploy/NamingResourcesImpl.java | 31 +++++++++++-----------
java/org/apache/catalina/filters/CorsFilter.java | 2 +-
18 files changed, 59 insertions(+), 47 deletions(-)
diff --git a/java/org/apache/catalina/core/ApplicationDispatcher.java
b/java/org/apache/catalina/core/ApplicationDispatcher.java
index 5c257619e6..8cb78131dc 100644
--- a/java/org/apache/catalina/core/ApplicationDispatcher.java
+++ b/java/org/apache/catalina/core/ApplicationDispatcher.java
@@ -450,9 +450,6 @@ final class ApplicationDispatcher implements
AsyncDispatcher, RequestDispatcher
/**
* Ask the resource represented by this RequestDispatcher to process the
associated request, and create (or append
* to) the associated response.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong>: This implementation assumes that
no filters are applied to a forwarded or
- * included resource, because they were already done for the original
request.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
diff --git a/java/org/apache/catalina/core/ApplicationHttpRequest.java
b/java/org/apache/catalina/core/ApplicationHttpRequest.java
index 24d7f51d43..de9c20bebc 100644
--- a/java/org/apache/catalina/core/ApplicationHttpRequest.java
+++ b/java/org/apache/catalina/core/ApplicationHttpRequest.java
@@ -54,7 +54,7 @@ import org.apache.tomcat.util.res.StringManager;
* Wrapper around a <code>jakarta.servlet.http.HttpServletRequest</code> that
transforms an application request object
* (which might be the original one passed to a servlet, or might be based on
the 2.3
* <code>jakarta.servlet.http.HttpServletRequestWrapper</code> class) back
into an internal
- * <code>org.apache.catalina.HttpRequest</code>.
+ * <code>org.apache.catalina.connector.Request</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
inheritance, all of the logic in
* <code>ApplicationRequest</code> is duplicated in
<code>ApplicationHttpRequest</code>. Make sure that you keep these
@@ -621,7 +621,8 @@ class ApplicationHttpRequest extends
HttpServletRequestWrapper {
// -------------------------------------------------------- Package Methods
/**
- * Recycle this request
+ * Recycle this request. Since there is no object reuse, this only ends
+ * the session access.
*/
public void recycle() {
if (session != null) {
diff --git a/java/org/apache/catalina/core/ApplicationHttpResponse.java
b/java/org/apache/catalina/core/ApplicationHttpResponse.java
index 7b397dbd5c..68c27e4e40 100644
--- a/java/org/apache/catalina/core/ApplicationHttpResponse.java
+++ b/java/org/apache/catalina/core/ApplicationHttpResponse.java
@@ -28,7 +28,7 @@ import jakarta.servlet.http.HttpServletResponseWrapper;
* Wrapper around a <code>jakarta.servlet.http.HttpServletResponse</code> that
transforms an application response object
* (which might be the original one passed to a servlet, or might be based on
the 2.3
* <code>jakarta.servlet.http.HttpServletResponseWrapper</code> class) back
into an internal
- * <code>org.apache.catalina.HttpResponse</code>.
+ * <code>org.apache.catalina.connector.Response</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
inheritance, all of the logic in
* <code>ApplicationResponse</code> is duplicated in
<code>ApplicationHttpResponse</code>. Make sure that you keep these
diff --git a/java/org/apache/catalina/core/ApplicationRequest.java
b/java/org/apache/catalina/core/ApplicationRequest.java
index f082455adc..b8ca244a1d 100644
--- a/java/org/apache/catalina/core/ApplicationRequest.java
+++ b/java/org/apache/catalina/core/ApplicationRequest.java
@@ -33,7 +33,7 @@ import org.apache.tomcat.util.res.StringManager;
* Wrapper around a <code>jakarta.servlet.ServletRequest</code> that
transforms an application request object (which
* might be the original one passed to a servlet, or might be based on the 2.3
* <code>jakarta.servlet.ServletRequestWrapper</code> class) back into an
internal
- * <code>org.apache.catalina.Request</code>.
+ * <code>org.apache.catalina.connector.Request</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
inheritance, all of the logic in
* <code>ApplicationRequest</code> is duplicated in
<code>ApplicationHttpRequest</code>. Make sure that you keep these
diff --git a/java/org/apache/catalina/core/ApplicationResponse.java
b/java/org/apache/catalina/core/ApplicationResponse.java
index c2e91370e2..1c2944b477 100644
--- a/java/org/apache/catalina/core/ApplicationResponse.java
+++ b/java/org/apache/catalina/core/ApplicationResponse.java
@@ -26,7 +26,7 @@ import jakarta.servlet.ServletResponseWrapper;
* Wrapper around a <code>jakarta.servlet.ServletResponse</code> that
transforms an application response object (which
* might be the original one passed to a servlet, or might be based on the 2.3
* <code>jakarta.servlet.ServletResponseWrapper</code> class) back into an
internal
- * <code>org.apache.catalina.Response</code>.
+ * <code>org.apache.catalina.connector.Response</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
inheritance, all of the logic in
* <code>ApplicationResponse</code> is duplicated in
<code>ApplicationHttpResponse</code>. Make sure that you keep these
diff --git a/java/org/apache/catalina/core/ApplicationServletRegistration.java
b/java/org/apache/catalina/core/ApplicationServletRegistration.java
index 3433932abb..93a2c47506 100644
--- a/java/org/apache/catalina/core/ApplicationServletRegistration.java
+++ b/java/org/apache/catalina/core/ApplicationServletRegistration.java
@@ -196,6 +196,7 @@ public class ApplicationServletRegistration implements
ServletRegistration.Dynam
*/
overrides.add(decodedUrlPatterns[i]);
} else {
+ // The conflicts list the original URL patterns passed
conflicts.add(urlPatterns[i]);
}
}
diff --git a/java/org/apache/catalina/core/AsyncContextImpl.java
b/java/org/apache/catalina/core/AsyncContextImpl.java
index f70bd2ef2f..9915d0b1e5 100644
--- a/java/org/apache/catalina/core/AsyncContextImpl.java
+++ b/java/org/apache/catalina/core/AsyncContextImpl.java
@@ -644,7 +644,7 @@ public class AsyncContextImpl implements AsyncContext,
AsyncContextCallback {
private void check() {
Request request = this.request;
- if (hasBeenRecycled.get()) {
+ if (hasBeenRecycled.get() || request == null) {
// AsyncContext has been recycled and should not be being used
throw new
IllegalStateException(sm.getString("asyncContextImpl.requestEnded"));
}
diff --git a/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
b/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
index 554d7e2c8a..de219d11d5 100644
--- a/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
+++ b/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
@@ -238,7 +238,7 @@ public class JreMemoryLeakPreventionListener implements
LifecycleListener {
// Set the default URL caching policy to not to cache
if (urlCacheProtection) {
- URLConnection.setDefaultUseCaches("JAR", false);
+ URLConnection.setDefaultUseCaches("jar", false);
}
/*
diff --git a/java/org/apache/catalina/core/NamingContextListener.java
b/java/org/apache/catalina/core/NamingContextListener.java
index 27f9711a84..8ea24c293c 100644
--- a/java/org/apache/catalina/core/NamingContextListener.java
+++ b/java/org/apache/catalina/core/NamingContextListener.java
@@ -37,13 +37,14 @@ import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
+import org.apache.catalina.Container;
import org.apache.catalina.Context;
-import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Server;
+import org.apache.catalina.Service;
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -1083,11 +1084,13 @@ public class NamingContextListener implements
LifecycleListener, PropertyChangeL
private javax.naming.Context getGlobalNamingContext() {
if (container instanceof Context) {
- Engine e = (Engine) ((Context) container).getParent().getParent();
- Server s = e.getService().getServer();
- // When the Service is an embedded Service, there is no Server
- if (s != null) {
- return s.getGlobalNamingContext();
+ Service service = Container.getService((Context) container);
+ if (service != null) {
+ Server s = service.getServer();
+ // When the Service is an embedded Service, there is no Server
+ if (s != null) {
+ return s.getGlobalNamingContext();
+ }
}
}
return null;
diff --git a/java/org/apache/catalina/core/StandardEngineValve.java
b/java/org/apache/catalina/core/StandardEngineValve.java
index 546c8d46ac..cf7ea22f82 100644
--- a/java/org/apache/catalina/core/StandardEngineValve.java
+++ b/java/org/apache/catalina/core/StandardEngineValve.java
@@ -56,8 +56,7 @@ final class StandardEngineValve extends ValveBase {
// Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
- // HTTP 0.9 or HTTP 1.0 request without a host when no default host
- // is defined.
+ // No Host found for this request (unknown server name or no
default host defined)
// Don't overwrite an existing error
if (!response.isError()) {
response.sendError(404);
diff --git a/java/org/apache/catalina/core/StandardHost.java
b/java/org/apache/catalina/core/StandardHost.java
index daaca98633..fbb55dfab9 100644
--- a/java/org/apache/catalina/core/StandardHost.java
+++ b/java/org/apache/catalina/core/StandardHost.java
@@ -502,9 +502,9 @@ public class StandardHost extends ContainerBase implements
Host {
*/
public void setErrorReportValveClass(String errorReportValveClass) {
- String oldErrorReportValveClassClass = this.errorReportValveClass;
+ String oldErrorReportValveClass = this.errorReportValveClass;
this.errorReportValveClass = errorReportValveClass;
- support.firePropertyChange("errorReportValveClass",
oldErrorReportValveClassClass, this.errorReportValveClass);
+ support.firePropertyChange("errorReportValveClass",
oldErrorReportValveClass, this.errorReportValveClass);
}
diff --git a/java/org/apache/catalina/core/StandardPipeline.java
b/java/org/apache/catalina/core/StandardPipeline.java
index 29fa0e5197..ca640db4ff 100644
--- a/java/org/apache/catalina/core/StandardPipeline.java
+++ b/java/org/apache/catalina/core/StandardPipeline.java
@@ -365,6 +365,7 @@ public class StandardPipeline extends LifecycleBase
implements Pipeline {
if (first == basic) {
first = null;
}
+ // Note: Removing the basic valve is done by replacing it using
setBasic
cleanupValve(valve);
diff --git a/java/org/apache/catalina/core/StandardVirtualThreadExecutor.java
b/java/org/apache/catalina/core/StandardVirtualThreadExecutor.java
index faa652b0f1..932f439590 100644
--- a/java/org/apache/catalina/core/StandardVirtualThreadExecutor.java
+++ b/java/org/apache/catalina/core/StandardVirtualThreadExecutor.java
@@ -99,8 +99,11 @@ public class StandardVirtualThreadExecutor extends
LifecycleMBeanBase implements
@Override
protected void stopInternal() throws LifecycleException {
- executor = null;
setState(LifecycleState.STOPPING);
+ if (executor != null) {
+ executor.shutdownNow();
+ }
+ executor = null;
}
@Override
diff --git a/java/org/apache/catalina/core/StandardWrapper.java
b/java/org/apache/catalina/core/StandardWrapper.java
index 3575ef79b8..4121a4e582 100644
--- a/java/org/apache/catalina/core/StandardWrapper.java
+++ b/java/org/apache/catalina/core/StandardWrapper.java
@@ -936,6 +936,8 @@ public class StandardWrapper extends ContainerBase
implements ServletConfig, Wra
}
}
+ ServletException servletException = null;
+
if (instanceInitialized) {
PrintStream out = System.out;
if (swallowOutput) {
@@ -948,9 +950,7 @@ public class StandardWrapper extends ContainerBase
implements ServletConfig, Wra
} catch (Throwable t) {
Throwable throwable =
ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(throwable);
- fireContainerEvent("unload", this);
- unloading = false;
- throw new
ServletException(sm.getString("standardWrapper.destroyException", getName()),
throwable);
+ servletException = new
ServletException(sm.getString("standardWrapper.destroyException", getName()),
throwable);
} finally {
// Annotation processing
if (!((Context) getParent()).getIgnoreAnnotations()) {
@@ -972,7 +972,6 @@ public class StandardWrapper extends ContainerBase
implements ServletConfig, Wra
}
}
}
- instance = null;
instanceInitialized = false;
}
}
@@ -986,6 +985,11 @@ public class StandardWrapper extends ContainerBase
implements ServletConfig, Wra
unloading = false;
fireContainerEvent("unload", this);
+
+ if (servletException != null) {
+ throw servletException;
+ }
+
}
@@ -1324,7 +1328,7 @@ public class StandardWrapper extends ContainerBase
implements ServletConfig, Wra
new MBeanNotificationInfo(new String[] {
"j2ee.state.running" }, Notification.class.getName(),
"servlet is running"),
new MBeanNotificationInfo(new String[] {
"j2ee.state.stopped" }, Notification.class.getName(),
- "servlet start to stopped"),
+ "servlet is stopping"),
new MBeanNotificationInfo(new String[] {
"j2ee.object.stopped" }, Notification.class.getName(),
"servlet is stopped"),
new MBeanNotificationInfo(new String[] {
"j2ee.object.deleted" }, Notification.class.getName(),
diff --git a/java/org/apache/catalina/core/StandardWrapperFacade.java
b/java/org/apache/catalina/core/StandardWrapperFacade.java
index 1128fea374..4432f99280 100644
--- a/java/org/apache/catalina/core/StandardWrapperFacade.java
+++ b/java/org/apache/catalina/core/StandardWrapperFacade.java
@@ -72,8 +72,8 @@ public final class StandardWrapperFacade implements
ServletConfig {
@Override
public ServletContext getServletContext() {
/*
- * This method may be called concurrently but the same context object
will always be returned. There is no
- * concurrency issue here.
+ * Multiple threads may initialize context concurrently, but the same
context/facade
+ * object is always returned, so this is functionally safe.
*/
if (context == null) {
context = config.getServletContext();
diff --git
a/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
b/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
index bc86774b6c..836e3686d9 100644
--- a/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
+++ b/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
@@ -18,9 +18,9 @@ package org.apache.catalina.core;
import java.util.concurrent.Executor;
+import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.Context;
-import org.apache.catalina.Engine;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
@@ -111,8 +111,10 @@ public class ThreadLocalLeakPreventionListener extends
FrameworkListener {
return;
}
- Engine engine = (Engine) context.getParent().getParent();
- Service service = engine.getService();
+ Service service = Container.getService(context);
+ if (service == null) {
+ return;
+ }
Connector[] connectors = service.findConnectors();
if (connectors != null) {
for (Connector connector : connectors) {
diff --git a/java/org/apache/catalina/deploy/NamingResourcesImpl.java
b/java/org/apache/catalina/deploy/NamingResourcesImpl.java
index ff0e38bf3e..850cc66acf 100644
--- a/java/org/apache/catalina/deploy/NamingResourcesImpl.java
+++ b/java/org/apache/catalina/deploy/NamingResourcesImpl.java
@@ -24,20 +24,20 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import javax.naming.NamingException;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
-import org.apache.catalina.Engine;
import org.apache.catalina.JmxEnabled;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Server;
+import org.apache.catalina.Service;
import org.apache.catalina.mbeans.MBeanUtils;
import org.apache.catalina.util.Introspection;
import org.apache.catalina.util.LifecycleMBeanBase;
@@ -100,7 +100,7 @@ public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializa
/**
* Set of naming entries, keyed by name.
*/
- private final Set<String> entries = new HashSet<>();
+ private final Set<String> entries = ConcurrentHashMap.newKeySet();
/**
@@ -175,7 +175,7 @@ public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializa
/**
* Set the container with which the naming resources are associated.
*
- * @param container the associated with the resources
+ * @param container the container associated with the resources
*/
public void setContainer(Object container) {
this.container = container;
@@ -303,15 +303,16 @@ public class NamingResourcesImpl extends
LifecycleMBeanBase implements Serializa
}
// Container should be an instance of Server or Context. If it is anything
- // else, return null which will trigger a NPE.
+ // else, return null.
private Server getServer() {
if (container instanceof Server) {
return (Server) container;
}
if (container instanceof Context) {
- // Could do this in one go. Lots of casts so split out for clarity
- Engine engine = (Engine) ((Context)
container).getParent().getParent();
- return engine.getService().getServer();
+ Service service = Container.getService((Context) container);
+ if (service != null) {
+ return service.getServer();
+ }
}
return null;
}
@@ -911,7 +912,7 @@ public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializa
// timing issues. Duplication registration is not an issue.
resourceRequireExplicitRegistration = true;
- for (ContextResource cr : resources.values()) {
+ for (ContextResource cr : findResources()) {
try {
MBeanUtils.createMBean(cr);
} catch (Exception e) {
@@ -919,7 +920,7 @@ public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializa
}
}
- for (ContextEnvironment ce : envs.values()) {
+ for (ContextEnvironment ce : findEnvironments()) {
try {
MBeanUtils.createMBean(ce);
} catch (Exception e) {
@@ -927,7 +928,7 @@ public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializa
}
}
- for (ContextResourceLink crl : resourceLinks.values()) {
+ for (ContextResourceLink crl : findResourceLinks()) {
try {
MBeanUtils.createMBean(crl);
} catch (Exception e) {
@@ -970,7 +971,7 @@ public class NamingResourcesImpl extends LifecycleMBeanBase
implements Serializa
log.warn(sm.getString("namingResources.cleanupNoContext",
container), e);
return;
}
- for (ContextResource cr : resources.values()) {
+ for (ContextResource cr : findResources()) {
if (cr.getSingleton()) {
String closeMethod = cr.getCloseMethod();
if (closeMethod != null && !closeMethod.isEmpty()) {
@@ -1026,7 +1027,7 @@ public class NamingResourcesImpl extends
LifecycleMBeanBase implements Serializa
resourceRequireExplicitRegistration = false;
// Destroy in reverse order to create, although it should not matter
- for (ContextResourceLink crl : resourceLinks.values()) {
+ for (ContextResourceLink crl : findResourceLinks()) {
try {
MBeanUtils.destroyMBean(crl);
} catch (Exception e) {
@@ -1034,7 +1035,7 @@ public class NamingResourcesImpl extends
LifecycleMBeanBase implements Serializa
}
}
- for (ContextEnvironment ce : envs.values()) {
+ for (ContextEnvironment ce : findEnvironments()) {
try {
MBeanUtils.destroyMBean(ce);
} catch (Exception e) {
@@ -1042,7 +1043,7 @@ public class NamingResourcesImpl extends
LifecycleMBeanBase implements Serializa
}
}
- for (ContextResource cr : resources.values()) {
+ for (ContextResource cr : findResources()) {
try {
MBeanUtils.destroyMBean(cr);
} catch (Exception e) {
diff --git a/java/org/apache/catalina/filters/CorsFilter.java
b/java/org/apache/catalina/filters/CorsFilter.java
index 7e0c8dca74..52be34ee19 100644
--- a/java/org/apache/catalina/filters/CorsFilter.java
+++ b/java/org/apache/catalina/filters/CorsFilter.java
@@ -73,7 +73,7 @@ import org.apache.tomcat.util.res.StringManager;
* {@link CorsFilter#doFilter(ServletRequest, ServletResponse, FilterChain)}
and add appropriate locking so that the
* {@code doFilter()} method executes with a consistent configuration.
*
- * @see <a href="http://www.w3.org/TR/cors/">CORS specification</a>
+ * @see <a href="https://fetch.spec.whatwg.org/#http-cors-protocol">CORS
specification</a>
*/
public class CorsFilter extends GenericFilter {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]