/* * 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 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.LifecycleException; import org.apache.catalina.LifecycleListener; import org.apache.catalina.authenticator.AuthenticatorBase; import org.apache.catalina.connector.Request; import org.apache.catalina.core.StandardContext; import org.apache.catalina.core.StandardHost; import org.apache.catalina.ha.context.ReplicatedContext; import org.apache.tomcat.util.MultiThrowable; 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 { req.getSession(true); 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() + "/"); Assert.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(); Assert.assertTrue(text, text.indexOf("") > 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(); Assert.assertTrue(text, text.indexOf("${(1==2) ? 3 : 4}") > 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() + "/"); Assert.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() + "/"); Assert.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() + "/"); Assert.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); Assert.assertEquals(HttpServletResponse.SC_OK, rc); Assert.assertTrue(res.toString().contains("