/* * 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.core; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.AsyncContext; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.ServletMapping; import org.junit.Assert; import org.junit.Test; import org.apache.catalina.Context; import org.apache.catalina.Wrapper; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; import org.apache.tomcat.util.buf.ByteChunk; public class TestApplicationMapping extends TomcatBaseTest { @Test public void testContextNonRootMappingContextRoot() throws Exception { doTestMapping("/dummy", "", "", "", "CONTEXT_ROOT"); } @Test public void testContextNonRootMappingDefault() throws Exception { doTestMapping("/dummy", "/", "/foo", "", "DEFAULT"); } @Test public void testContextNonRootMappingExtension() throws Exception { doTestMapping("/dummy", "*.test", "/foo/bar.test", "foo/bar", "EXTENSION"); } @Test public void testContextNonRootMappingExact() throws Exception { doTestMapping("/dummy", "/foo/bar", "/foo/bar", "foo/bar", "EXACT"); } @Test public void testContextNonRootMappingPathNone() throws Exception { doTestMapping("/dummy", "/foo/bar/*", "/foo/bar", null, "PATH"); } @Test public void testContextNonRootMappingPathSeparatorOnly() throws Exception { doTestMapping("/dummy", "/foo/bar/*", "/foo/bar/", "", "PATH"); } @Test public void testContextNonRootMappingPath() throws Exception { doTestMapping("/dummy", "/foo/bar/*", "/foo/bar/foo2", "foo2", "PATH"); } @Test public void testContextRootMappingContextRoot() throws Exception { doTestMapping("", "", "", "", "CONTEXT_ROOT"); } @Test public void testContextRootMappingDefault() throws Exception { doTestMapping("", "/", "/foo", "", "DEFAULT"); } @Test public void testContextRootMappingExtension() throws Exception { doTestMapping("", "*.test", "/foo/bar.test", "foo/bar", "EXTENSION"); } @Test public void testContextRootMappingExact() throws Exception { doTestMapping("", "/foo/bar", "/foo/bar", "foo/bar", "EXACT"); } @Test public void testContextRootMappingPath() throws Exception { doTestMapping("", "/foo/bar/*", "/foo/bar/foo2", "foo2", "PATH"); } private void doTestMapping(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { doTestMappingDirect(contextPath, mapping, requestPath, matchValue, matchType); tearDown(); setUp(); doTestMappingInclude(contextPath, mapping, requestPath, matchValue, matchType); tearDown(); setUp(); doTestMappingNamedInclude(contextPath, mapping, requestPath, matchValue, matchType); tearDown(); setUp(); doTestMappingForward(contextPath, mapping, requestPath, matchValue, matchType); tearDown(); setUp(); doTestMappingNamedForward(contextPath, mapping, requestPath, matchValue, matchType); tearDown(); setUp(); doTestMappingAsync(contextPath, mapping, requestPath, matchValue, matchType); } private void doTestMappingDirect(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext(contextPath, null); Tomcat.addServlet(ctx, "Mapping", new MappingServlet()); ctx.addServletMappingDecoded(mapping, "Mapping"); tomcat.start(); ByteChunk bc = getUrl("http://localhost:" + getPort() + contextPath + requestPath); String body = bc.toString(); Assert.assertTrue(body, body.contains("MatchValue=[" + matchValue + "]")); Assert.assertTrue(body, body.contains("Pattern=[" + mapping + "]")); Assert.assertTrue(body, body.contains("MatchType=[" + matchType + "]")); Assert.assertTrue(body, body.contains("ServletName=[Mapping]")); } private void doTestMappingInclude(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext(contextPath, null); Tomcat.addServlet(ctx, "Include", new IncludeServlet()); ctx.addServletMappingDecoded(mapping, "Include"); Tomcat.addServlet(ctx, "Mapping", new MappingServlet()); ctx.addServletMappingDecoded("/mapping", "Mapping"); tomcat.start(); ByteChunk bc = getUrl("http://localhost:" + getPort() + contextPath + requestPath); String body = bc.toString(); Assert.assertTrue(body, body.contains("MatchValue=[" + matchValue + "]")); Assert.assertTrue(body, body.contains("Pattern=[" + mapping + "]")); Assert.assertTrue(body, body.contains("MatchType=[" + matchType + "]")); Assert.assertTrue(body, body.contains("ServletName=[Include]")); Assert.assertTrue(body, body.contains("IncludeMatchValue=[mapping]")); Assert.assertTrue(body, body.contains("IncludePattern=[/mapping]")); Assert.assertTrue(body, body.contains("IncludeMatchType=[EXACT]")); Assert.assertTrue(body, body.contains("IncludeServletName=[Mapping]")); } private void doTestMappingNamedInclude(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext(contextPath, null); Tomcat.addServlet(ctx, "Include", new NamedIncludeServlet()); ctx.addServletMappingDecoded(mapping, "Include"); Tomcat.addServlet(ctx, "Mapping", new MappingServlet()); ctx.addServletMappingDecoded("/mapping", "Mapping"); tomcat.start(); ByteChunk bc = getUrl("http://localhost:" + getPort() + contextPath + requestPath); String body = bc.toString(); Assert.assertTrue(body, body.contains("MatchValue=[" + matchValue + "]")); Assert.assertTrue(body, body.contains("Pattern=[" + mapping + "]")); Assert.assertTrue(body, body.contains("MatchType=[" + matchType + "]")); Assert.assertTrue(body, body.contains("ServletName=[Include]")); } private void doTestMappingForward(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext(contextPath, null); Tomcat.addServlet(ctx, "Forward", new ForwardServlet()); ctx.addServletMappingDecoded(mapping, "Forward"); Tomcat.addServlet(ctx, "Mapping", new MappingServlet()); ctx.addServletMappingDecoded("/mapping", "Mapping"); tomcat.start(); ByteChunk bc = getUrl("http://localhost:" + getPort() + contextPath + requestPath); String body = bc.toString(); Assert.assertTrue(body, body.contains("MatchValue=[mapping]")); Assert.assertTrue(body, body.contains("Pattern=[/mapping]")); Assert.assertTrue(body, body.contains("MatchType=[EXACT]")); Assert.assertTrue(body, body.contains("ServletName=[Mapping]")); Assert.assertTrue(body, body.contains("ForwardMatchValue=[" + matchValue + "]")); Assert.assertTrue(body, body.contains("ForwardPattern=[" + mapping + "]")); Assert.assertTrue(body, body.contains("ForwardMatchType=[" + matchType + "]")); Assert.assertTrue(body, body.contains("ForwardServletName=[Forward]")); } private void doTestMappingNamedForward(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext(contextPath, null); Tomcat.addServlet(ctx, "Forward", new NamedForwardServlet()); ctx.addServletMappingDecoded(mapping, "Forward"); Tomcat.addServlet(ctx, "Mapping", new MappingServlet()); ctx.addServletMappingDecoded("/mapping", "Mapping"); tomcat.start(); ByteChunk bc = getUrl("http://localhost:" + getPort() + contextPath + requestPath); String body = bc.toString(); Assert.assertTrue(body, body.contains("MatchValue=[" + matchValue + "]")); Assert.assertTrue(body, body.contains("Pattern=[" + mapping + "]")); Assert.assertTrue(body, body.contains("MatchType=[" + matchType + "]")); Assert.assertTrue(body, body.contains("ServletName=[Forward]")); } private void doTestMappingAsync(String contextPath, String mapping, String requestPath, String matchValue, String matchType) throws Exception { Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context ctx = tomcat.addContext(contextPath, null); Wrapper w = Tomcat.addServlet(ctx, "Async", new AsyncServlet()); w.setAsyncSupported(true); ctx.addServletMappingDecoded(mapping, "Async"); Tomcat.addServlet(ctx, "Mapping", new MappingServlet()); ctx.addServletMappingDecoded("/mapping", "Mapping"); tomcat.start(); ByteChunk bc = getUrl("http://localhost:" + getPort() + contextPath + requestPath); String body = bc.toString(); Assert.assertTrue(body, body.contains("MatchValue=[mapping]")); Assert.assertTrue(body, body.contains("Pattern=[/mapping]")); Assert.assertTrue(body, body.contains("MatchType=[EXACT]")); Assert.assertTrue(body, body.contains("ServletName=[Mapping]")); Assert.assertTrue(body, body.contains("AsyncMatchValue=[" + matchValue + "]")); Assert.assertTrue(body, body.contains("AsyncPattern=[" + mapping + "]")); Assert.assertTrue(body, body.contains("AsyncMatchType=[" + matchType + "]")); Assert.assertTrue(body, body.contains("AsyncServletName=[Async]")); } private static class IncludeServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher rd = req.getRequestDispatcher("/mapping"); rd.include(req, resp); } } private static class NamedIncludeServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher rd = req.getServletContext().getNamedDispatcher("Mapping"); rd.include(req, resp); } } private static class NamedForwardServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher rd = req.getServletContext().getNamedDispatcher("Mapping"); rd.forward(req, resp); } } private static class ForwardServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher rd = req.getRequestDispatcher("/mapping"); rd.forward(req, resp); } } private static class AsyncServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AsyncContext ac = req.startAsync(); ac.dispatch("/mapping"); } } private static class MappingServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain;charset=UTF-8"); PrintWriter pw = resp.getWriter(); ServletMapping mapping = req.getServletMapping(); pw.println("MatchValue=[" + mapping.getMatchValue() + "]"); pw.println("Pattern=[" + mapping.getPattern() + "]"); pw.println("MatchType=[" + mapping.getMappingMatch() + "]"); pw.println("ServletName=[" + mapping.getServletName() + "]"); ServletMapping includeMapping = (ServletMapping) req.getAttribute(RequestDispatcher.INCLUDE_MAPPING); if (includeMapping != null) { pw.println("IncludeMatchValue=[" + includeMapping.getMatchValue() + "]"); pw.println("IncludePattern=[" + includeMapping.getPattern() + "]"); pw.println("IncludeMatchType=[" + includeMapping.getMappingMatch() + "]"); pw.println("IncludeServletName=[" + includeMapping.getServletName() + "]"); } ServletMapping forwardMapping = (ServletMapping) req.getAttribute(RequestDispatcher.FORWARD_MAPPING); if (forwardMapping != null) { pw.println("ForwardMatchValue=[" + forwardMapping.getMatchValue() + "]"); pw.println("ForwardPattern=[" + forwardMapping.getPattern() + "]"); pw.println("ForwardMatchType=[" + forwardMapping.getMappingMatch() + "]"); pw.println("ForwardServletName=[" + forwardMapping.getServletName() + "]"); } ServletMapping asyncMapping = (ServletMapping) req.getAttribute(AsyncContext.ASYNC_MAPPING); if (asyncMapping != null) { pw.println("AsyncMatchValue=[" + asyncMapping.getMatchValue() + "]"); pw.println("AsyncPattern=[" + asyncMapping.getPattern() + "]"); pw.println("AsyncMatchType=[" + asyncMapping.getMappingMatch() + "]"); pw.println("AsyncServletName=[" + asyncMapping.getServletName() + "]"); } } } }