Repository: tomee Updated Branches: refs/heads/tomee-1.7.x 528fa1245 -> ddb55fbcf
use wrapper to determine if we are in a jaxrs request or not Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/be873a77 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/be873a77 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/be873a77 Branch: refs/heads/tomee-1.7.x Commit: be873a774d3d8998e3bf40ee0b0afb91abb61fc9 Parents: 528fa12 Author: Romain Manni-Bucau <[email protected]> Authored: Mon Jan 26 14:25:48 2015 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Mon Jan 26 14:25:48 2015 +0100 ---------------------------------------------------------------------- .../tomee/webservices/CXFJAXRSFilter.java | 88 +++++++++++++++----- .../tomee/webservices/TomcatRsRegistry.java | 19 +++-- .../org/apache/tomee/jaxrs/ReflectionTest.java | 7 +- 3 files changed, 80 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/be873a77/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/CXFJAXRSFilter.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/CXFJAXRSFilter.java b/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/CXFJAXRSFilter.java index 13bbcde..39907ca 100644 --- a/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/CXFJAXRSFilter.java +++ b/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/CXFJAXRSFilter.java @@ -16,8 +16,9 @@ */ package org.apache.tomee.webservices; -import org.apache.catalina.servlets.DefaultServlet; -import org.apache.openejb.core.ParentClassLoaderFinder; +import org.apache.catalina.Wrapper; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.RequestFacade; import org.apache.openejb.server.cxf.rs.CxfRsHttpListener; import org.apache.openejb.server.httpd.ServletRequestAdapter; import org.apache.openejb.server.httpd.ServletResponseAdapter; @@ -29,27 +30,29 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; 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.io.InputStream; import java.lang.reflect.Field; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; public class CXFJAXRSFilter implements Filter { - private static final Field SERVLET_FIELD; + private static final Field REQUEST; static { - Field servletFieldTmp = null; try { - final Class<?> clazz = ParentClassLoaderFinder.Helper.get().loadClass("org.apache.catalina.core.ApplicationFilterChain"); - servletFieldTmp = clazz.getDeclaredField("servlet"); - servletFieldTmp.setAccessible(true); - } catch (final Exception e) { - // no-op + REQUEST = RequestFacade.class.getDeclaredField("request"); + } catch (final NoSuchFieldException e) { + throw new IllegalStateException(e); } - SERVLET_FIELD = servletFieldTmp; + REQUEST.setAccessible(true); } private final CxfRsHttpListener delegate; private final String[] welcomeFiles; + private final ConcurrentMap<Wrapper, Boolean> mappingByServlet = new ConcurrentHashMap<Wrapper, Boolean>(); + private String mapping; public CXFJAXRSFilter(final CxfRsHttpListener delegate, final String[] welcomeFiles) { this.delegate = delegate; @@ -62,7 +65,7 @@ public class CXFJAXRSFilter implements Filter { @Override public void init(final FilterConfig filterConfig) throws ServletException { - // no-op + mapping = filterConfig.getInitParameter("mapping"); } @Override @@ -76,7 +79,7 @@ public class CXFJAXRSFilter implements Filter { final HttpServletResponse httpServletResponse = HttpServletResponse.class.cast(response); if (CxfRsHttpListener.TRY_STATIC_RESOURCES) { // else we just want jaxrs - if (isServlet(chain)) { + if (servletMappingIsUnderRestPath(httpServletRequest)) { chain.doFilter(request, response); return; } @@ -96,19 +99,62 @@ public class CXFJAXRSFilter implements Filter { } } - // see org.apache.tomcat.util.http.mapper.Mapper.internalMapWrapper - private boolean isServlet(final FilterChain chain) { - // will not work if we are not the first filter - which is likely the case the keep security etc - - // and the chain is wrapped which is more unlikely so this should work as long as these untyped constraints are respected: - // - org.apache.catalina.core.ApplicationFilterChain name is stable (case on tomcat 8 for now) - // - ApplicationFilterChain as a field servlet with the expected servlet + private boolean servletMappingIsUnderRestPath(final HttpServletRequest request) { + final HttpServletRequest unwrapped = unwrap(request); + if (!RequestFacade.class.isInstance(unwrapped)) { + return false; + } + + final Request tr; try { - return SERVLET_FIELD != null - && "org.apache.catalina.core.ApplicationFilterChain".equals(chain.getClass().getName()) - && !DefaultServlet.class.isInstance(SERVLET_FIELD.get(chain)); + tr = Request.class.cast(REQUEST.get(unwrapped)); } catch (final IllegalAccessException e) { return false; } + final Wrapper wrapper = tr.getWrapper(); + if (wrapper == null || mapping == null) { + return false; + } + + Boolean accept = mappingByServlet.get(wrapper); + if (accept == null) { + accept = false; + if (!"org.apache.catalina.servlets.DefaultServlet".equals(wrapper.getServletClass())) { + for (final String mapping : wrapper.findMappings()) { + if (!mapping.isEmpty() && !"/*".equals(mapping) && !"/".equals(mapping) && mapping.startsWith(this.mapping)) { + accept = true; + break; + } + } + } + mappingByServlet.putIfAbsent(wrapper, accept); + return accept; + } + + return false; + } + + private HttpServletRequest unwrap(final HttpServletRequest request) { + HttpServletRequest unwrapped = request; + boolean changed; + do { + changed = false; + while (HttpServletRequestWrapper.class.isInstance(unwrapped)) { + final HttpServletRequest tmp = HttpServletRequest.class.cast(HttpServletRequestWrapper.class.cast(unwrapped).getRequest()); + if (tmp != unwrapped) { + unwrapped = tmp; + } else { + changed = false; // quit + break; + } + changed = true; + } + while (ServletRequestAdapter.class.isInstance(unwrapped)) { + unwrapped = ServletRequestAdapter.class.cast(unwrapped).getRequest(); + changed = true; + } + } while (changed); + return unwrapped; } @Override http://git-wip-us.apache.org/repos/asf/tomee/blob/be873a77/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java b/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java index 8f185cb..d460d14 100644 --- a/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java +++ b/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java @@ -106,15 +106,6 @@ public class TomcatRsRegistry implements RsRegistry { final CxfRsHttpListener cxfRsHttpListener = findCxfRsHttpListener(listener); final String description = "tomee-jaxrs-" + listener; - final FilterDef filterDef = new FilterDef(); - filterDef.setAsyncSupported("true"); - filterDef.setDescription(description); - filterDef.setFilterName(description); - filterDef.setDisplayName(description); - filterDef.setFilter(new CXFJAXRSFilter(cxfRsHttpListener, context.findWelcomeFiles())); - filterDef.setFilterClass(CXFJAXRSFilter.class.getName()); - context.addFilterDef(filterDef); - String mapping = completePath; if (!completePath.endsWith("/*")) { // respect servlet spec (!= from our embedded listeners) if (completePath.endsWith("*")) { @@ -126,6 +117,16 @@ public class TomcatRsRegistry implements RsRegistry { final String urlPattern = removeWebContext(webContext, mapping); cxfRsHttpListener.setUrlPattern(urlPattern.substring(0, urlPattern.length() - 1)); + final FilterDef filterDef = new FilterDef(); + filterDef.setAsyncSupported("true"); + filterDef.setDescription(description); + filterDef.setFilterName(description); + filterDef.setDisplayName(description); + filterDef.setFilter(new CXFJAXRSFilter(cxfRsHttpListener, context.findWelcomeFiles())); + filterDef.setFilterClass(CXFJAXRSFilter.class.getName()); + filterDef.addInitParameter("mapping", urlPattern.substring(0, urlPattern.length() - "/*".length())); // just keep base path + context.addFilterDef(filterDef); + final FilterMap filterMap = new FilterMap(); filterMap.addURLPattern(urlPattern); filterMap.setFilterName(filterDef.getFilterName()); http://git-wip-us.apache.org/repos/asf/tomee/blob/be873a77/tomee/tomee-jaxrs/src/test/java/org/apache/tomee/jaxrs/ReflectionTest.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-jaxrs/src/test/java/org/apache/tomee/jaxrs/ReflectionTest.java b/tomee/tomee-jaxrs/src/test/java/org/apache/tomee/jaxrs/ReflectionTest.java index 9bd5fcd..98ebf07 100644 --- a/tomee/tomee-jaxrs/src/test/java/org/apache/tomee/jaxrs/ReflectionTest.java +++ b/tomee/tomee-jaxrs/src/test/java/org/apache/tomee/jaxrs/ReflectionTest.java @@ -16,16 +16,15 @@ */ package org.apache.tomee.jaxrs; +import org.apache.catalina.connector.Request; import org.junit.Test; -import javax.servlet.Servlet; - import static org.junit.Assert.assertEquals; public class ReflectionTest { @Test // a quick test to break the build if upgrading tomcat our reflection will silently be broken public void breakTheBuildIfWhatWeUseChanged() throws ClassNotFoundException, NoSuchFieldException { - final Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.core.ApplicationFilterChain"); - assertEquals(Servlet.class, clazz.getDeclaredField("servlet").getType()); + final Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass("org.apache.catalina.connector.RequestFacade"); + assertEquals(Request.class, clazz.getDeclaredField("request").getType()); } }
