Author: markt Date: Mon Dec 1 14:58:44 2014 New Revision: 1642698 URL: http://svn.apache.org/r1642698 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=57190 Fix ServletContext.getContext() when parallel deployment is in use.
Modified: tomcat/tc8.0.x/trunk/ (props changed) tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/ApplicationContext.java tomcat/tc8.0.x/trunk/test/org/apache/catalina/core/TestApplicationContext.java tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc8.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1642679,1642697 Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/ApplicationContext.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/ApplicationContext.java?rev=1642698&r1=1642697&r2=1642698&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/ApplicationContext.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/core/ApplicationContext.java Mon Dec 1 14:58:44 2014 @@ -253,16 +253,30 @@ public class ApplicationContext Context child = null; try { - Host host = (Host) context.getParent(); - String mapuri = uri; - while (true) { - child = (Context) host.findChild(mapuri); - if (child != null) - break; - int slash = mapuri.lastIndexOf('/'); - if (slash < 0) - break; - mapuri = mapuri.substring(0, slash); + // Look for an exact match + Container host = context.getParent(); + child = (Context) host.findChild(uri); + + // Remove any version information and use the mapper + if (child == null) { + int i = uri.indexOf("##"); + if (i > -1) { + uri = uri.substring(0, i); + } + // Note: This could be more efficient with a dedicated Mapper + // method but such an implementation would require some + // refactoring of the Mapper to avoid copy/paste of + // existing code. + MessageBytes hostMB = MessageBytes.newInstance(); + hostMB.setString(host.getName()); + + MessageBytes pathMB = MessageBytes.newInstance(); + pathMB.setString(uri); + + MappingData mappingData = new MappingData(); + ((Engine) host.getParent()).getService().getMapper().map(hostMB, pathMB, null, mappingData); + + child = mappingData.context; } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); Modified: tomcat/tc8.0.x/trunk/test/org/apache/catalina/core/TestApplicationContext.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/catalina/core/TestApplicationContext.java?rev=1642698&r1=1642697&r2=1642698&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/test/org/apache/catalina/core/TestApplicationContext.java (original) +++ tomcat/tc8.0.x/trunk/test/org/apache/catalina/core/TestApplicationContext.java Mon Dec 1 14:58:44 2014 @@ -16,20 +16,30 @@ */ package org.apache.catalina.core; +import java.io.IOException; +import java.io.PrintWriter; import java.util.Collection; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.descriptor.JspConfigDescriptor; import javax.servlet.descriptor.JspPropertyGroupDescriptor; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Test; +import org.apache.catalina.Context; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.Tomcat.FixContextListener; import org.apache.catalina.startup.TomcatBaseTest; import org.apache.tomcat.util.buf.ByteChunk; @@ -146,4 +156,83 @@ public class TestApplicationContext exte getTomcatInstance().start(); getServletContext().setInitParameter("name", "value"); } + + + /* + * Cross-context requests with parallel deployment + */ + @Test + public void testBug57190() throws Exception { + Tomcat tomcat = getTomcatInstance(); + + Context foo1 = new StandardContext(); + foo1.setName("/foo##1"); + foo1.setPath("/foo"); + foo1.addLifecycleListener(new FixContextListener()); + foo1.addLifecycleListener(new SetIdListener("foo1")); + tomcat.getHost().addChild(foo1); + + Context foo2 = new StandardContext(); + foo2.setName("/foo##2"); + foo2.setPath("/foo"); + foo2.addLifecycleListener(new FixContextListener()); + foo2.addLifecycleListener(new SetIdListener("foo2")); + tomcat.getHost().addChild(foo2); + + Context bar = tomcat.addContext("/bar", null); + bar.addLifecycleListener(new SetIdListener("bar")); + + Context ctx = tomcat.addContext("", null); + ctx.setCrossContext(true); + + Tomcat.addServlet(ctx, "Bug57190Servlet", new Bug57190Servlet()); + ctx.addServletMapping("/", "Bug57190Servlet"); + + tomcat.start(); + + ByteChunk res = getUrl("http://localhost:" + getPort() + "/"); + String body = res.toString(); + + Assert.assertTrue(body, body.contains("01-bar")); + Assert.assertTrue(body, body.contains("02-foo2")); + Assert.assertTrue(body, body.contains("03-foo1")); + Assert.assertTrue(body, body.contains("04-foo2")); + Assert.assertTrue(body, body.contains("05-foo2")); + } + + + private static class Bug57190Servlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/plain"); + PrintWriter pw = resp.getWriter(); + ServletContext sc = req.getServletContext(); + pw.println("01-" + sc.getContext("/bar").getInitParameter("id")); + pw.println("02-" + sc.getContext("/foo").getInitParameter("id")); + pw.println("03-" + sc.getContext("/foo##1").getInitParameter("id")); + pw.println("04-" + sc.getContext("/foo##2").getInitParameter("id")); + pw.println("05-" + sc.getContext("/foo##3").getInitParameter("id")); + } + } + + + private static class SetIdListener implements LifecycleListener { + + private final String id; + + public SetIdListener(String id) { + this.id = id; + } + + @Override + public void lifecycleEvent(LifecycleEvent event) { + if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType())) { + ((Context) event.getSource()).getServletContext().setInitParameter("id", id); + } + } + } } Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1642698&r1=1642697&r2=1642698&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Mon Dec 1 14:58:44 2014 @@ -61,6 +61,11 @@ requests that use an HTTP method defined in RFC 7231. (markt) </fix> <fix> + <bug>57190</bug>: Fix <code>ServletContext.getContext(String)</code> + when parallel deployment is used so that the correct ServletContext is + returned. (markt) + </fix> + <fix> <bug>57208</bug>: Prevent NPE in JNDI Realm when no results are found in a directory context for a user with specified user name. Based on a patch provided by Jason McIntosh. (violetagg) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org