| /* |
| * 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.startup; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.Reader; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpSession; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import org.apache.catalina.Context; |
| import org.apache.catalina.Host; |
| import org.apache.catalina.LifecycleEvent; |
| import org.apache.catalina.LifecycleListener; |
| import org.apache.catalina.core.StandardContext; |
| import org.apache.catalina.core.StandardHost; |
| import org.apache.catalina.ha.context.ReplicatedContext; |
| import org.apache.tomcat.util.buf.ByteChunk; |
| import org.apache.tomcat.util.descriptor.web.ContextEnvironment; |
| import org.apache.tomcat.util.descriptor.web.ContextResourceLink; |
| import org.apache.tomcat.websocket.server.WsContextListener; |
| |
| public class TestTomcat extends TomcatBaseTest { |
| |
| /** |
| * Simple servlet to test in-line registration. |
| */ |
| public static class HelloWorld extends HttpServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void doGet(HttpServletRequest req, HttpServletResponse res) |
| throws IOException { |
| res.getWriter().write("Hello world"); |
| } |
| } |
| |
| /** |
| * Simple servlet to test the default session manager. |
| */ |
| public static class HelloWorldSession extends HttpServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void doGet(HttpServletRequest req, HttpServletResponse res) |
| throws IOException { |
| HttpSession s = req.getSession(true); |
| s.getId(); |
| res.getWriter().write("Hello world"); |
| } |
| } |
| |
| /** |
| * Simple servlet to test JNDI |
| */ |
| public static class HelloWorldJndi extends HttpServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| private static final String JNDI_ENV_NAME = "test"; |
| |
| @Override |
| public void doGet(HttpServletRequest req, HttpServletResponse res) |
| throws IOException { |
| |
| String name = null; |
| |
| try { |
| javax.naming.Context initCtx = new InitialContext(); |
| javax.naming.Context envCtx = |
| (javax.naming.Context) initCtx.lookup("java:comp/env"); |
| name = (String) envCtx.lookup(JNDI_ENV_NAME); |
| } catch (NamingException e) { |
| throw new IOException(e); |
| } |
| |
| res.getWriter().write("Hello, " + name); |
| } |
| } |
| |
| /** |
| * Servlet that tries to obtain a URL for WEB-INF/web.xml |
| */ |
| public static class GetResource extends HttpServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void doGet(HttpServletRequest req, HttpServletResponse res) |
| throws IOException { |
| URL url = req.getServletContext().getResource("/WEB-INF/web.xml"); |
| |
| res.getWriter().write("The URL obtained for /WEB-INF/web.xml was "); |
| if (url == null) { |
| res.getWriter().write("null"); |
| } else { |
| res.getWriter().write(url.toString() + "\n"); |
| res.getWriter().write("The first 20 characters of that resource are:\n"); |
| |
| // Read some content from the resource |
| URLConnection conn = url.openConnection(); |
| |
| char cbuf[] = new char[20]; |
| int read = 0; |
| try (InputStream is = conn.getInputStream(); |
| Reader reader = new InputStreamReader(is)) { |
| while (read < 20) { |
| int len = reader.read(cbuf, read, cbuf.length - read); |
| res.getWriter().write(cbuf, read, len); |
| read = read + len; |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Simple servlet to test initialization of servlet instances. |
| */ |
| private static class InitCount extends HttpServlet { |
| |
| private static final long serialVersionUID = 1L; |
| |
| private AtomicInteger callCount = new AtomicInteger(0); |
| |
| @Override |
| public void init() throws ServletException { |
| super.init(); |
| callCount.incrementAndGet(); |
| } |
| |
| @Override |
| protected void doGet(HttpServletRequest req, HttpServletResponse resp) |
| throws ServletException, IOException { |
| resp.setContentType("text/plain"); |
| resp.getWriter().print("OK"); |
| } |
| |
| public int getCallCount() { |
| return callCount.intValue(); |
| } |
| } |
| |
| |
| /* |
| * Start tomcat with a single context and one |
| * servlet - all programmatic, no server.xml or |
| * web.xml used. |
| * |
| * @throws Exception |
| */ |
| @Test |
| public void testProgrammatic() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext("", null); |
| |
| Tomcat.addServlet(ctx, "myServlet", new HelloWorld()); |
| ctx.addServletMappingDecoded("/", "myServlet"); |
| |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + "/"); |
| assertEquals("Hello world", res.toString()); |
| } |
| |
| @Test |
| public void testSingleWebapp() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appDir = new File(getBuildDirectory(), "webapps/examples"); |
| // app dir is relative to server home |
| Context ctxt = tomcat.addWebapp( |
| null, "/examples", appDir.getAbsolutePath()); |
| ctxt.addApplicationListener(WsContextListener.class.getName()); |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + |
| "/examples/servlets/servlet/HelloWorldExample"); |
| String text = res.toString(); |
| assertTrue(text, text.indexOf("<a href=\"../helloworld.html\">") > 0); |
| } |
| |
| @Test |
| public void testJsps() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appDir = new File(getBuildDirectory(), "webapps/examples"); |
| // app dir is relative to server home |
| Context ctxt = tomcat.addWebapp( |
| null, "/examples", appDir.getAbsolutePath()); |
| ctxt.addApplicationListener(WsContextListener.class.getName()); |
| |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + |
| "/examples/jsp/jsp2/el/basic-arithmetic.jsp"); |
| String text = res.toString(); |
| assertTrue(text, text.indexOf("<td>${(1==2) ? 3 : 4}</td>") > 0); |
| } |
| |
| @Test |
| public void testSession() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext("", null); |
| |
| Tomcat.addServlet(ctx, "myServlet", new HelloWorldSession()); |
| ctx.addServletMappingDecoded("/", "myServlet"); |
| |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + "/"); |
| assertEquals("Hello world", res.toString()); |
| } |
| |
| @Test |
| public void testLaunchTime() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| long t0 = System.currentTimeMillis(); |
| tomcat.addContext(null, "", "."); |
| tomcat.start(); |
| log.info("Tomcat started in [" + (System.currentTimeMillis() - t0) |
| + "] ms"); |
| } |
| |
| |
| /* |
| * Test for enabling JNDI. |
| */ |
| @Test |
| public void testEnableNaming() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext("", null); |
| |
| // Enable JNDI - it is disabled by default |
| tomcat.enableNaming(); |
| |
| ContextEnvironment environment = new ContextEnvironment(); |
| environment.setType("java.lang.String"); |
| environment.setName(HelloWorldJndi.JNDI_ENV_NAME); |
| environment.setValue("Tomcat User"); |
| ctx.getNamingResources().addEnvironment(environment); |
| |
| Tomcat.addServlet(ctx, "jndiServlet", new HelloWorldJndi()); |
| ctx.addServletMappingDecoded("/", "jndiServlet"); |
| |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + "/"); |
| assertEquals("Hello, Tomcat User", res.toString()); |
| } |
| |
| /* |
| * Test for enabling JNDI and using global resources. |
| */ |
| @Test |
| public void testEnableNamingGlobal() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext("", null); |
| |
| // Enable JNDI - it is disabled by default |
| tomcat.enableNaming(); |
| |
| ContextEnvironment environment = new ContextEnvironment(); |
| environment.setType("java.lang.String"); |
| environment.setName("globalTest"); |
| environment.setValue("Tomcat User"); |
| tomcat.getServer().getGlobalNamingResources().addEnvironment(environment); |
| |
| ContextResourceLink link = new ContextResourceLink(); |
| link.setGlobal("globalTest"); |
| link.setName(HelloWorldJndi.JNDI_ENV_NAME); |
| link.setType("java.lang.String"); |
| ctx.getNamingResources().addResourceLink(link); |
| |
| Tomcat.addServlet(ctx, "jndiServlet", new HelloWorldJndi()); |
| ctx.addServletMappingDecoded("/", "jndiServlet"); |
| |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + "/"); |
| assertEquals("Hello, Tomcat User", res.toString()); |
| } |
| |
| |
| /* |
| * Test for https://bz.apache.org/bugzilla/show_bug.cgi?id=47866 |
| */ |
| @Test |
| public void testGetResource() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| String contextPath = "/examples"; |
| |
| File appDir = new File(getBuildDirectory(), "webapps" + contextPath); |
| // app dir is relative to server home |
| Context ctx = |
| tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); |
| ctx.addApplicationListener(WsContextListener.class.getName()); |
| |
| Tomcat.addServlet(ctx, "testGetResource", new GetResource()); |
| ctx.addServletMappingDecoded("/testGetResource", "testGetResource"); |
| |
| tomcat.start(); |
| |
| ByteChunk res = new ByteChunk(); |
| |
| int rc =getUrl("http://localhost:" + getPort() + contextPath + |
| "/testGetResource", res, null); |
| assertEquals(HttpServletResponse.SC_OK, rc); |
| assertTrue(res.toString().contains("<?xml version=\"1.0\" ")); |
| } |
| |
| @Test |
| public void testBug50826() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| String contextPath = "/examples"; |
| |
| File appDir = new File(getBuildDirectory(), "webapps" + contextPath); |
| // app dir is relative to server home |
| tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); |
| |
| Exception e = null; |
| try { |
| tomcat.destroy(); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| e = ex; |
| } |
| assertNull(e); |
| } |
| |
| @Test |
| public void testBug53301() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext("", null); |
| |
| InitCount initCount = new InitCount(); |
| Tomcat.addServlet(ctx, "initCount", initCount); |
| ctx.addServletMappingDecoded("/", "initCount"); |
| |
| tomcat.start(); |
| |
| ByteChunk res = getUrl("http://localhost:" + getPort() + "/"); |
| assertEquals("OK", res.toString()); |
| |
| assertEquals(1, initCount.getCallCount()); |
| } |
| |
| @Test |
| public void testGetWebappConfigFileFromDirectory() { |
| Tomcat tomcat = new Tomcat(); |
| assertNotNull(tomcat.getWebappConfigFile("test/deployment/dirContext", "")); |
| } |
| |
| @Test |
| public void testGetWebappConfigFileFromDirectoryNegative() { |
| Tomcat tomcat = new Tomcat(); |
| assertNull(tomcat.getWebappConfigFile("test/deployment/dirNoContext", "")); |
| } |
| |
| @Test |
| public void testGetWebappConfigFileFromJar() { |
| Tomcat tomcat = new Tomcat(); |
| assertNotNull(tomcat.getWebappConfigFile("test/deployment/context.war", "")); |
| } |
| |
| @Test |
| public void testGetWebappConfigFileFromJarNegative() { |
| Tomcat tomcat = new Tomcat(); |
| assertNull(tomcat.getWebappConfigFile("test/deployment/noContext.war", "")); |
| } |
| |
| @Test |
| public void testBug51526() throws Exception { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appFile = new File("test/deployment/context.war"); |
| StandardContext context = (StandardContext) tomcat.addWebapp(null, "/test", |
| appFile.getAbsolutePath()); |
| |
| tomcat.start(); |
| |
| assertEquals("WAR_CONTEXT", context.getSessionCookieName()); |
| } |
| |
| @Test |
| public void testGetDefaultContextPerAddWebapp() { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| File appFile = new File("test/deployment/context.war"); |
| Context context = tomcat.addWebapp(null, |
| "/test", appFile.getAbsolutePath()); |
| |
| assertEquals(StandardContext.class.getName(), context.getClass() |
| .getName()); |
| } |
| |
| @Test |
| public void testGetBrokenContextPerAddWepapp() { |
| Tomcat tomcat = getTomcatInstance(); |
| Host host = tomcat.getHost(); |
| if (host instanceof StandardHost) { |
| ((StandardHost) host).setContextClass("InvalidContextClassName"); |
| } |
| |
| try { |
| File appFile = new File("test/deployment/context.war"); |
| tomcat.addWebapp(null, "/test", appFile.getAbsolutePath()); |
| fail(); |
| } catch (IllegalArgumentException e) { |
| // OK |
| } |
| } |
| |
| @Test |
| public void testGetCustomContextPerAddWebappWithNullHost() { |
| Tomcat tomcat = getTomcatInstance(); |
| Host host = tomcat.getHost(); |
| if (host instanceof StandardHost) { |
| ((StandardHost) host).setContextClass(ReplicatedContext.class |
| .getName()); |
| } |
| |
| File appFile = new File("test/deployment/context.war"); |
| Context context = tomcat.addWebapp(null, "/test", |
| appFile.getAbsolutePath()); |
| |
| assertEquals(ReplicatedContext.class.getName(), context.getClass() |
| .getName()); |
| } |
| |
| @Test |
| public void testGetCustomContextPerAddWebappWithHost() { |
| Tomcat tomcat = getTomcatInstance(); |
| Host host = tomcat.getHost(); |
| if (host instanceof StandardHost) { |
| ((StandardHost) host).setContextClass(ReplicatedContext.class |
| .getName()); |
| } |
| |
| File appFile = new File("test/deployment/context.war"); |
| Context context = tomcat.addWebapp(host, "/test", |
| appFile.getAbsolutePath()); |
| |
| assertEquals(ReplicatedContext.class.getName(), context.getClass() |
| .getName()); |
| } |
| |
| @Test |
| public void testGetDefaultContextPerAddContext() { |
| Tomcat tomcat = getTomcatInstance(); |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext(null, "", null); |
| assertEquals(StandardContext.class.getName(), ctx.getClass().getName()); |
| } |
| |
| @Test |
| public void testGetBrokenContextPerAddContext() { |
| Tomcat tomcat = getTomcatInstance(); |
| Host host = tomcat.getHost(); |
| if (host instanceof StandardHost) { |
| ((StandardHost) host).setContextClass("InvalidContextClassName"); |
| } |
| |
| // No file system docBase required |
| try { |
| tomcat.addContext(null, "", null); |
| fail(); |
| } catch (IllegalArgumentException e) { |
| // OK |
| } |
| } |
| |
| @Test |
| public void testGetCustomContextPerAddContextWithHost() { |
| Tomcat tomcat = getTomcatInstance(); |
| Host host = tomcat.getHost(); |
| if (host instanceof StandardHost) { |
| ((StandardHost) host).setContextClass(ReplicatedContext.class |
| .getName()); |
| } |
| |
| // No file system docBase required |
| Context ctx = tomcat.addContext(host, "", null); |
| assertEquals(ReplicatedContext.class.getName(), ctx.getClass() |
| .getName()); |
| } |
| |
| @Test |
| public void testCustomContextConfig() throws Exception { |
| |
| Tomcat tomcat = getTomcatInstance(); |
| |
| tomcat.getHost().setConfigClass(CustomContextConfig.class.getName()); |
| |
| File docBase = new File("test/webapp"); |
| tomcat.addWebapp("/test", docBase.getAbsolutePath()); |
| |
| tomcat.start(); |
| |
| Assert.assertTrue(CustomContextConfig.isUsed()); |
| } |
| |
| public static class CustomContextConfig implements LifecycleListener { |
| |
| private static volatile boolean used = false; |
| |
| public static boolean isUsed() { |
| return used; |
| } |
| |
| @Override |
| public void lifecycleEvent(LifecycleEvent event) { |
| // Hack via a static since we can't pass an instance in the test. |
| used = true; |
| } |
| } |
| } |