Repository: tomee Updated Branches: refs/heads/develop 9040ece1d -> d62af41b4
dont conflict with servlet cause of our jaxrs filter Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/d62af41b Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/d62af41b Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/d62af41b Branch: refs/heads/develop Commit: d62af41b4ad81c91e926b01cf5a08a34009f2f88 Parents: 9040ece Author: Romain Manni-Bucau <[email protected]> Authored: Fri Jan 16 19:29:39 2015 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Fri Jan 16 19:29:39 2015 +0100 ---------------------------------------------------------------------- .../staticresources/AvoidConflictTest.java | 12 ++++- .../jaxrs/staticresources/PreviousFilter.java | 46 ++++++++++++++++++++ .../jaxrs/staticresources/SimpleServlet.java | 32 ++++++++++++++ .../jaxrs/staticresources/TheResource.java | 8 ++++ .../tomee/webservices/CXFJAXRSFilter.java | 43 ++++++++++++++++-- .../org/apache/tomee/jaxrs/ReflectionTest.java | 31 +++++++++++++ 6 files changed, 168 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/d62af41b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java index 602c15c..8504469 100644 --- a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java @@ -37,7 +37,7 @@ public class AvoidConflictTest { @Deployment(testable = false) public static Archive<?> war() { return ShrinkWrap.create(WebArchive.class, "app.war") - .addClass(TheResource.class) + .addClasses(TheResource.class, SimpleServlet.class, PreviousFilter.class) .addAsWebResource(new StringAsset("static"), "index.html"); } @@ -53,4 +53,14 @@ public class AvoidConflictTest { public void staticResource() throws IOException { assertEquals("static", IO.slurp(url)); } + + @Test + public void servlet() throws IOException { + assertEquals("Servlet!", IO.slurp(new URL(url + "servlet"))); + } + + @Test + public void filterOrder() throws IOException { + assertEquals("I'm the first", IO.slurp(new URL(url.toExternalForm() + "gotFilter"))); + } } http://git-wip-us.apache.org/repos/asf/tomee/blob/d62af41b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/PreviousFilter.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/PreviousFilter.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/PreviousFilter.java new file mode 100644 index 0000000..3b42026 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/PreviousFilter.java @@ -0,0 +1,46 @@ +/* + * 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.openejb.arquillian.tests.jaxrs.staticresources; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import java.io.IOException; + +@WebFilter("/*") +public class PreviousFilter implements Filter { + @Override + public void init(final FilterConfig filterConfig) throws ServletException { + // no-op + } + + @Override + public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, + final FilterChain filterChain) throws IOException, ServletException { + servletRequest.setAttribute("filter", "I'm the first"); + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + // no-op + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/d62af41b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/SimpleServlet.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/SimpleServlet.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/SimpleServlet.java new file mode 100644 index 0000000..cc3843d --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/SimpleServlet.java @@ -0,0 +1,32 @@ +/* + * 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.openejb.arquillian.tests.jaxrs.staticresources; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet("/servlet") +public class SimpleServlet extends HttpServlet { + @Override + protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + resp.getWriter().write("Servlet!"); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/d62af41b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java index 1f50f5e..95051fd 100644 --- a/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java @@ -16,8 +16,10 @@ */ package org.apache.openejb.arquillian.tests.jaxrs.staticresources; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.core.Context; @Path("/") public class TheResource { @@ -26,4 +28,10 @@ public class TheResource { public String get() { return "resource"; } + + @GET + @Path("gotFilter") + public String filter(@Context HttpServletRequest request) { + return String.class.cast(request.getAttribute("filter")); + } } http://git-wip-us.apache.org/repos/asf/tomee/blob/d62af41b/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 61f9358..85c2445 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,6 +16,8 @@ */ package org.apache.tomee.webservices; +import org.apache.catalina.servlets.DefaultServlet; +import org.apache.openejb.core.ParentClassLoaderFinder; import org.apache.openejb.server.cxf.rs.CxfRsHttpListener; import org.apache.openejb.server.httpd.ServletRequestAdapter; import org.apache.openejb.server.httpd.ServletResponseAdapter; @@ -30,8 +32,22 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Field; public class CXFJAXRSFilter implements Filter { + private static final Field SERVLET_FIELD; + 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 + } + SERVLET_FIELD = servletFieldTmp; + } + private final CxfRsHttpListener delegate; private final String[] welcomeFiles; @@ -59,12 +75,18 @@ public class CXFJAXRSFilter implements Filter { final HttpServletRequest httpServletRequest = HttpServletRequest.class.cast(request); final HttpServletResponse httpServletResponse = HttpServletResponse.class.cast(response); - if (CxfRsHttpListener.TRY_STATIC_RESOURCES || delegate.matchPath(httpServletRequest)) { - final InputStream staticContent = delegate.findStaticContent(httpServletRequest, welcomeFiles); - if (staticContent != null) { + if (CxfRsHttpListener.TRY_STATIC_RESOURCES) { // else 100% JAXRS + if (isServlet(chain)) { chain.doFilter(request, response); return; } + if (delegate.matchPath(httpServletRequest)) { + final InputStream staticContent = delegate.findStaticContent(httpServletRequest, welcomeFiles); + if (staticContent != null) { + chain.doFilter(request, response); + return; + } + } } try { @@ -76,6 +98,21 @@ 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 respeted: + // - org.apache.catalina.core.ApplicationFilterChain name is stable (case on tomcat 8 for now) + // - ApplicationFilterChain as a field servlet with the expected servlet + try { + return SERVLET_FIELD != null + && "org.apache.catalina.core.ApplicationFilterChain".equals(chain.getClass().getName()) + && !DefaultServlet.class.isInstance(SERVLET_FIELD.get(chain)); + } catch (final IllegalAccessException e) { + return false; + } + } + @Override public void destroy() { // no-op http://git-wip-us.apache.org/repos/asf/tomee/blob/d62af41b/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 new file mode 100644 index 0000000..9bd5fcd --- /dev/null +++ b/tomee/tomee-jaxrs/src/test/java/org/apache/tomee/jaxrs/ReflectionTest.java @@ -0,0 +1,31 @@ +/* + * 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.tomee.jaxrs; + +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()); + } +}
