This is an automated email from the ASF dual-hosted git repository. jlmonteiro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 057ed7adade08d8c2132ab1c8bc6fa367c93e946 Author: Jean-Louis Monteiro <[email protected]> AuthorDate: Fri Apr 30 14:07:30 2021 +0200 TOMEE-3213 TOMEE-3214 TOMEE-3215 Refine our wrapping mechanism for CDI such as it does not break TCK --- .../org/apache/openejb/server/httpd/EEFilter.java | 63 ++++++++++++++++------ .../openejb/server/httpd/HttpRequestImpl.java | 2 +- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java index 38ed02f..26f3507 100644 --- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java +++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java @@ -36,6 +36,7 @@ import javax.servlet.ServletRequestEvent; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; @@ -59,13 +60,13 @@ public class EEFilter implements Filter { final boolean shouldWrap = active && HttpServletRequest.class.isInstance(servletRequest); if (!HttpServletRequest.class.isInstance(servletRequest)) { filterChain.doFilter(shouldWrap ? - new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), this) : servletRequest, servletResponse); + new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), servletResponse, this) : servletRequest, servletResponse); return; } WebBeansContext ctx; filterChain.doFilter(servletRequest.isAsyncSupported() && (ctx = WebBeansContext.currentInstance()) != null ? - new CdiRequest(HttpServletRequest.class.cast(servletRequest), ctx, this) : - (shouldWrap ? new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), this) : servletRequest), + new CdiRequest(HttpServletRequest.class.cast(servletRequest), servletResponse, ctx, this) : + (shouldWrap ? new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), servletResponse, this) : servletRequest), servletResponse); } @@ -79,10 +80,12 @@ public class EEFilter implements Filter { } public static class NoCdiRequest extends HttpServletRequestWrapper { + private final ServletResponse response; private final EEFilter filter; - public NoCdiRequest(final HttpServletRequest cast, final EEFilter filter) { + public NoCdiRequest(final HttpServletRequest cast, final ServletResponse response, final EEFilter filter) { super(cast); + this.response = response; this.filter = filter; } @@ -104,8 +107,15 @@ public class EEFilter implements Filter { @Override public boolean equals(final Object obj) { // unwrap and delegate + if (obj instanceof NoCdiRequest /* and CDI Request */) { + return getRequest().equals(((NoCdiRequest) obj).getRequest()); + } return getRequest().equals(obj); } + + protected ServletResponse getResponse() { + return response; + } } public static class CdiRequest extends NoCdiRequest { @@ -114,22 +124,22 @@ public class EEFilter implements Filter { // it's a request so not multi-threaded private final AtomicReference<AsynContextWrapper> asyncContextWrapperReference = new AtomicReference<>(); - public CdiRequest(final HttpServletRequest cast, final WebBeansContext webBeansContext, final EEFilter filter) { - super(cast, filter); + public CdiRequest(final HttpServletRequest cast, final ServletResponse response, final WebBeansContext webBeansContext, final EEFilter filter) { + super(cast, response, filter); this.webBeansContext = webBeansContext; } @Override public AsyncContext startAsync() throws IllegalStateException { asyncContextWrapperReference.compareAndSet(null, - new AsynContextWrapper(super.startAsync(), this, webBeansContext)); + new AsynContextWrapper(super.startAsync(), this, getResponse(), webBeansContext)); return asyncContextWrapperReference.get(); } @Override public AsyncContext startAsync(final ServletRequest servletRequest, final ServletResponse servletResponse) throws IllegalStateException { asyncContextWrapperReference.compareAndSet(null, - new AsynContextWrapper(super.startAsync(servletRequest, servletResponse), servletRequest, webBeansContext)); + new AsynContextWrapper(super.startAsync(servletRequest, servletResponse), servletRequest, servletResponse, webBeansContext)); return asyncContextWrapperReference.get(); } @@ -143,14 +153,17 @@ public class EEFilter implements Filter { public static class AsynContextWrapper implements AsyncContext { private final AsyncContext delegate; private final CdiAppContextsService service; - private final ServletRequest request; + private final ServletResponse response; + private volatile ServletRequest request; private volatile ServletRequestEvent event; - public AsynContextWrapper(final AsyncContext asyncContext, final ServletRequest request, final WebBeansContext webBeansContext) { + public AsynContextWrapper(final AsyncContext asyncContext, final ServletRequest request, + final ServletResponse response, final WebBeansContext webBeansContext) { this.delegate = asyncContext; this.service = CdiAppContextsService.class.cast(webBeansContext.getService(ContextsService.class)); this.event = null; this.request = request; + this.response = response; } private boolean startRequestScope() { @@ -179,7 +192,10 @@ public class EEFilter implements Filter { @Override public ServletRequest getRequest() { - return request; + if (request != null) { + return request; + } + return delegate.getRequest(); } @Override @@ -195,7 +211,12 @@ public class EEFilter implements Filter { // Unfortunately we pass in the wrapped request so the flag is false // we need to override the value returned by Tomcat in case we are wrapping the request if (request instanceof NoCdiRequest) { // and CdiRequest - return request == delegate.getRequest(); // Tomcat should have this as the request and not the RequestFacade + final NoCdiRequest noCdiRequest = (NoCdiRequest) this.request; + // Tomcat should have this as the request and not the RequestFacade because of the wrapping + // compare with the response we captured during wrapping + // they might have been wrapped bu the user during the start + return noCdiRequest == delegate.getRequest() + && noCdiRequest.getResponse() == delegate.getResponse(); } } return tomcatHasOriginalRequestAndResponse; @@ -203,17 +224,29 @@ public class EEFilter implements Filter { @Override public void dispatch() { - delegate.dispatch(); + try { + delegate.dispatch(); + } finally { + request = null; + } } @Override public void dispatch(final String s) { - delegate.dispatch(s); + try { + delegate.dispatch(s); + } finally { + request = null; + } } @Override public void dispatch(final ServletContext servletContext, final String s) { - delegate.dispatch(servletContext, s); + try { + delegate.dispatch(servletContext, s); + } finally { + request = null; + } } @Override diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java index 79b5654..0ba3e7c 100644 --- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java +++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java @@ -1040,7 +1040,7 @@ public class HttpRequestImpl implements HttpRequest { final WebBeansContext webBeansContext = AppFinder.findAppContextOrWeb( Thread.currentThread().getContextClassLoader(), AppFinder.WebBeansContextTransformer.INSTANCE); return webBeansContext != null ? - new EEFilter.AsynContextWrapper(asyncContext, servletRequest, webBeansContext) : asyncContext; + new EEFilter.AsynContextWrapper(asyncContext, servletRequest, servletResponse, webBeansContext) : asyncContext; } public void addInternalParameter(final String key, final String val) {
