| /* |
| * 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.catalina.mapper; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.HttpURLConnection; |
| import java.util.HashMap; |
| import java.util.List; |
| |
| import javax.servlet.ServletException; |
| 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.core.StandardContext; |
| import org.apache.catalina.startup.Tomcat; |
| import org.apache.catalina.startup.TomcatBaseTest; |
| import org.apache.catalina.valves.RemoteAddrValve; |
| import org.apache.tomcat.util.buf.ByteChunk; |
| import org.apache.tomcat.util.descriptor.web.SecurityCollection; |
| import org.apache.tomcat.util.descriptor.web.SecurityConstraint; |
| import org.apache.tomcat.websocket.server.WsContextListener; |
| |
| /** |
| * Mapper tests that use real web applications on a running Tomcat. |
| */ |
| public class TestMapperWebapps extends TomcatBaseTest{ |
| |
| @Test |
| public void testContextRoot_Bug53339() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| tomcat.enableNaming(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext("", null); |
| |
| Tomcat.addServlet(ctx, "Bug53356", new Bug53356Servlet()); |
| ctx.addServletMapping("", "Bug53356"); |
| |
| tomcat.start(); |
| |
| ByteChunk body = getUrl("http://localhost:" + getPort()); |
| |
| Assert.assertEquals("OK", body.toString()); |
| } |
| |
| private static class Bug53356Servlet extends HttpServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| protected void doGet(HttpServletRequest req, HttpServletResponse resp) |
| throws ServletException, IOException { |
| // Confirm behaviour as per Servlet 12.2 |
| boolean pass = "/".equals(req.getPathInfo()); |
| if (pass) { |
| pass = "".equals(req.getServletPath()); |
| } |
| if (pass) { |
| pass = "".equals(req.getContextPath()); |
| } |
| |
| resp.setContentType("text/plain"); |
| if (pass) { |
| resp.getWriter().write("OK"); |
| } else { |
| resp.getWriter().write("FAIL"); |
| } |
| } |
| } |
| |
| @Test |
| public void testContextReload_Bug56658_Bug56882() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appDir = new File(getBuildDirectory(), "webapps/examples"); |
| // app dir is relative to server home |
| org.apache.catalina.Context ctxt = tomcat.addWebapp( |
| null, "/examples", appDir.getAbsolutePath()); |
| ctxt.addApplicationListener(WsContextListener.class.getName()); |
| tomcat.start(); |
| |
| // The tests are from TestTomcat#testSingleWebapp(), #testJsps() |
| // We reload the context and verify that the pages are still accessible |
| ByteChunk res; |
| String text; |
| |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/servlets/servlet/HelloWorldExample"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("<h1>Hello World!</h1>")); |
| |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/jsp/jsp2/el/basic-arithmetic.jsp"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("<td>${(1==2) ? 3 : 4}</td>")); |
| |
| res = getUrl("http://localhost:" + getPort() + "/examples/index.html"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("<title>Apache Tomcat Examples</title>")); |
| |
| long timeA = System.currentTimeMillis(); |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/jsp/include/include.jsp"); |
| String timestamp = findCommonPrefix(timeA, System.currentTimeMillis()); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains( |
| "In place evaluation of another JSP which gives you the current time: " + timestamp)); |
| Assert.assertTrue(text, text.contains( |
| "To get the current time in ms")); |
| Assert.assertTrue(text, text.contains( |
| "by including the output of another JSP: " + timestamp)); |
| Assert.assertTrue(text, text.contains(":-)")); |
| |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/jsp/forward/forward.jsp"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("VM Memory usage")); |
| |
| ctxt.reload(); |
| |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/servlets/servlet/HelloWorldExample"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("<h1>Hello World!</h1>")); |
| |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/jsp/jsp2/el/basic-arithmetic.jsp"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("<td>${(1==2) ? 3 : 4}</td>")); |
| |
| res = getUrl("http://localhost:" + getPort() + "/examples/index.html"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("<title>Apache Tomcat Examples</title>")); |
| |
| timeA = System.currentTimeMillis(); |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/jsp/include/include.jsp"); |
| timestamp = findCommonPrefix(timeA, System.currentTimeMillis()); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains( |
| "In place evaluation of another JSP which gives you the current time: " + timestamp)); |
| Assert.assertTrue(text, text.contains( |
| "To get the current time in ms")); |
| Assert.assertTrue(text, text.contains( |
| "by including the output of another JSP: " + timestamp)); |
| Assert.assertTrue(text, text.contains(":-)")); |
| |
| res = getUrl("http://localhost:" + getPort() |
| + "/examples/jsp/forward/forward.jsp"); |
| text = res.toString(); |
| Assert.assertTrue(text, text.contains("VM Memory usage")); |
| } |
| |
| @Test |
| public void testWelcomeFileNotStrict() throws Exception { |
| |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appDir = new File("test/webapp"); |
| |
| StandardContext ctxt = (StandardContext) tomcat.addWebapp(null, "/test", |
| appDir.getAbsolutePath()); |
| ctxt.setReplaceWelcomeFiles(true); |
| ctxt.addWelcomeFile("index.jsp"); |
| // Mapping for *.do is defined in web.xml |
| ctxt.addWelcomeFile("index.do"); |
| |
| tomcat.start(); |
| ByteChunk bc = new ByteChunk(); |
| int rc = getUrl("http://localhost:" + getPort() + |
| "/test/welcome-files", bc, new HashMap<String,List<String>>()); |
| Assert.assertEquals(HttpServletResponse.SC_OK, rc); |
| Assert.assertTrue(bc.toString().contains("JSP")); |
| |
| rc = getUrl("http://localhost:" + getPort() + |
| "/test/welcome-files/sub", bc, |
| new HashMap<String,List<String>>()); |
| Assert.assertEquals(HttpServletResponse.SC_OK, rc); |
| Assert.assertTrue(bc.toString().contains("Servlet")); |
| } |
| |
| @Test |
| public void testWelcomeFileStrict() throws Exception { |
| |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appDir = new File("test/webapp"); |
| |
| StandardContext ctxt = (StandardContext) tomcat.addWebapp(null, "/test", |
| appDir.getAbsolutePath()); |
| ctxt.setReplaceWelcomeFiles(true); |
| ctxt.addWelcomeFile("index.jsp"); |
| // Mapping for *.do is defined in web.xml |
| ctxt.addWelcomeFile("index.do"); |
| |
| // Simulate STRICT_SERVLET_COMPLIANCE |
| ctxt.setResourceOnlyServlets(""); |
| |
| tomcat.start(); |
| ByteChunk bc = new ByteChunk(); |
| int rc = getUrl("http://localhost:" + getPort() + |
| "/test/welcome-files", bc, new HashMap<String,List<String>>()); |
| Assert.assertEquals(HttpServletResponse.SC_OK, rc); |
| Assert.assertTrue(bc.toString().contains("JSP")); |
| |
| rc = getUrl("http://localhost:" + getPort() + |
| "/test/welcome-files/sub", bc, |
| new HashMap<String,List<String>>()); |
| Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, rc); |
| } |
| |
| @Test |
| public void testRedirect() throws Exception { |
| // Disable the following of redirects for this test only |
| boolean originalValue = HttpURLConnection.getFollowRedirects(); |
| HttpURLConnection.setFollowRedirects(false); |
| try { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // Use standard test webapp as ROOT |
| File rootDir = new File("test/webapp"); |
| org.apache.catalina.Context root = |
| tomcat.addWebapp(null, "", rootDir.getAbsolutePath()); |
| |
| // Add a security constraint |
| SecurityConstraint constraint = new SecurityConstraint(); |
| SecurityCollection collection = new SecurityCollection(); |
| collection.addPattern("/welcome-files/*"); |
| collection.addPattern("/welcome-files"); |
| constraint.addCollection(collection); |
| constraint.addAuthRole("foo"); |
| root.addConstraint(constraint); |
| |
| // Also make examples available |
| File examplesDir = new File(getBuildDirectory(), "webapps/examples"); |
| org.apache.catalina.Context examples = tomcat.addWebapp( |
| null, "/examples", examplesDir.getAbsolutePath()); |
| // Then block access to the examples to test redirection |
| RemoteAddrValve rav = new RemoteAddrValve(); |
| rav.setDeny(".*"); |
| rav.setDenyStatus(404); |
| examples.getPipeline().addValve(rav); |
| |
| tomcat.start(); |
| |
| // Redirects within a web application |
| doRedirectTest("/welcome-files", 401); |
| doRedirectTest("/welcome-files/", 401); |
| |
| doRedirectTest("/jsp", 302); |
| doRedirectTest("/jsp/", 404); |
| |
| doRedirectTest("/WEB-INF", 404); |
| doRedirectTest("/WEB-INF/", 404); |
| |
| // Redirects between web applications |
| doRedirectTest("/examples", 404); |
| doRedirectTest("/examples/", 404); |
| } finally { |
| HttpURLConnection.setFollowRedirects(originalValue); |
| } |
| } |
| |
| |
| private void doRedirectTest(String path, int expected) throws IOException { |
| ByteChunk bc = new ByteChunk(); |
| int rc = getUrl("http://localhost:" + getPort() + path, bc, null); |
| Assert.assertEquals(expected, rc); |
| } |
| |
| |
| /** |
| * Prepare a string to search in messages that contain a timestamp, when it |
| * is known that the timestamp was printed between {@code timeA} and |
| * {@code timeB}. |
| */ |
| private static String findCommonPrefix(long timeA, long timeB) { |
| while ((timeA != timeB) && timeA > 0) { |
| timeA /= 10; |
| timeB /= 10; |
| } |
| return String.valueOf(timeA); |
| } |
| } |