/*
 * 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.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
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.fail;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;

import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Manager;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.session.ManagerBase;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.util.IOTools;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.webresources.StandardRoot;
import org.apache.coyote.http11.Http11NioProtocol;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.websocket.CaseInsensitiveKeyMap;

/**
 * Base test case that provides a Tomcat instance for each test - mainly so we
 * don't have to keep writing the cleanup code.
 */
public abstract class TomcatBaseTest extends LoggingBaseTest {
    private Tomcat tomcat;
    private boolean accessLogEnabled = false;

    public static final String TEMP_DIR = System.getProperty("java.io.tmpdir");

    /**
     * Make the Tomcat instance available to sub-classes.
     *
     * @return A Tomcat instance without any pre-configured web applications
     */
    public Tomcat getTomcatInstance() {
        return tomcat;
    }

    /**
     * Make the Tomcat instance preconfigured with test/webapp available to
     * sub-classes.
     * @param addJstl Should JSTL support be added to the test webapp
     * @param start   Should the Tomcat instance be started
     *
     * @return A Tomcat instance pre-configured with the web application located
     *         at test/webapp
     *
     * @throws LifecycleException If a problem occurs while starting the
     *                            instance
     */
    public Tomcat getTomcatInstanceTestWebapp(boolean addJstl, boolean start)
            throws LifecycleException {
        File appDir = new File("test/webapp");
        Context ctx = tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());

        if (addJstl) {
            File lib = new File("webapps/examples/WEB-INF/lib");
            ctx.setResources(new StandardRoot(ctx));
            ctx.getResources().createWebResourceSet(
                    WebResourceRoot.ResourceSetType.POST, "/WEB-INF/lib",
                    lib.getAbsolutePath(), null, "/");
        }

        if (start) {
            tomcat.start();
        }
        return tomcat;
    }

    /*
     * Sub-classes need to know port so they can connect
     */
    public int getPort() {
        return tomcat.getConnector().getLocalPort();
    }

    /*
     * Sub-classes may want to check, whether an AccessLogValve is active
     */
    public boolean isAccessLogEnabled() {
        return accessLogEnabled;
    }

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();

        // Trigger loading of catalina.properties
        CatalinaProperties.getProperty("foo");

        File appBase = new File(getTemporaryDirectory(), "webapps");
        if (!appBase.exists() && !appBase.mkdir()) {
            fail("Unable to create appBase for test");
        }

        tomcat = new TomcatWithFastSessionIDs();

        String protocol = getProtocol();
        Connector connector = new Connector(protocol);
        // Listen only on localhost
        connector.setAttribute("address",
                InetAddress.getByName("localhost").getHostAddress());
        // Use random free port
        connector.setPort(0);
        // Mainly set to reduce timeouts during async tests
        connector.setAttribute("connectionTimeout", "3000");
        tomcat.getService().addConnector(connector);
        tomcat.setConnector(connector);

        // Add AprLifecycleListener if we are using the Apr connector
        if (protocol.contains("Apr")) {
            StandardServer server = (StandardServer) tomcat.getServer();
            AprLifecycleListener listener = new AprLifecycleListener();
            listener.setSSLRandomSeed("/dev/urandom");
            server.addLifecycleListener(listener);
            connector.setAttribute("pollerThreadCount", Integer.valueOf(1));
        }

        File catalinaBase = getTemporaryDirectory();
        tomcat.setBaseDir(catalinaBase.getAbsolutePath());
        tomcat.getHost().setAppBase(appBase.getAbsolutePath());

        accessLogEnabled = Boolean.parseBoolean(
            System.getProperty("tomcat.test.accesslog", "false"));
        if (accessLogEnabled) {
            String accessLogDirectory = System
                    .getProperty("tomcat.test.reports");
            if (accessLogDirectory == null) {
                accessLogDirectory = new File(getBuildDirectory(), "logs")
                        .toString();
            }
            AccessLogValve alv = new AccessLogValve();
            alv.setDirectory(accessLogDirectory);
            alv.setPattern("%h %l %u %t \"%r\" %s %b %I %D");
            tomcat.getHost().getPipeline().addValve(alv);
        }

        // Cannot delete the whole tempDir, because logs are there,
        // but delete known subdirectories of it.
        addDeleteOnTearDown(new File(catalinaBase, "webapps"));
        addDeleteOnTearDown(new File(catalinaBase, "work"));
    }

    protected String getProtocol() {
        // Has a protocol been specified
        String protocol = System.getProperty("tomcat.test.protocol");

        // Use NIO by default starting with Tomcat 8
        if (protocol == null) {
            protocol = Http11NioProtocol.class.getName();
        }

        return protocol;
    }

    @After
    @Override
    public void tearDown() throws Exception {
        try {
            // Some tests may call tomcat.destroy(), some tests may just call
            // tomcat.stop(), some not call either method. Make sure that stop()
            // & destroy() are called as necessary.
            if (tomcat.server != null
                    && tomcat.server.getState() != LifecycleState.DESTROYED) {
                if (tomcat.server.getState() != LifecycleState.STOPPED) {
                    tomcat.stop();
                }
                tomcat.destroy();
            }
        } finally {
            super.tearDown();
        }
    }

    /**
     * Simple Hello World servlet for use by test cases
     */
    public static final class HelloWorldServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        public static final String RESPONSE_TEXT =
            "<html><body><p>Hello World</p></body></html>";

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            PrintWriter out = resp.getWriter();
            out.print(RESPONSE_TEXT);
        }
    }


    public static final class RequestDescriptor {

        private final Map<String, String> requestInfo = new HashMap<>();
        private final Map<String, String> contextInitParameters = new HashMap<>();
        private final Map<String, String> contextAttributes = new HashMap<>();
        private final Map<String, String> headers = new CaseInsensitiveKeyMap<>();
        private final Map<String, String> attributes = new HashMap<>();
        private final Map<String, String> params = new HashMap<>();
        private final Map<String, String> sessionAttributes = new HashMap<>();

        public Map<String, String> getRequestInfo() {
            return requestInfo;
        }

        public Map<String, String> getContextInitParameters() {
            return contextInitParameters;
        }

        public Map<String, String> getContextAttributes() {
            return contextAttributes;
        }

        public Map<String, String> getHeaders() {
            return headers;
        }

        public Map<String, String> getAttributes() {
            return attributes;
        }

        public Map<String, String> getParams() {
            return params;
        }

        public Map<String, String> getSessionAttributes() {
            return sessionAttributes;
        }

        public String getRequestInfo(String name) {
            return requestInfo.get(name);
        }

        public void putRequestInfo(String name, String value) {
            requestInfo.put(name, value);
        }

        public String getContextInitParameter(String name) {
            return contextInitParameters.get(name);
        }

        public void putContextInitParameter(String name, String value) {
            contextInitParameters.put(name, value);
        }

        public String getContextAttribute(String name) {
            return contextAttributes.get(name);
        }

        public void putContextAttribute(String name, String value) {
            contextAttributes.put(name, value);
        }

        public String getHeader(String name) {
            return headers.get(name);
        }

        public void putHeader(String name, String value) {
            headers.put(name, value);
        }

        public String getAttribute(String name) {
            return attributes.get(name);
        }

        public void putAttribute(String name, String value) {
            attributes.put(name, value);
        }

        public String getParam(String name) {
            return params.get(name);
        }

        public void putParam(String name, String value) {
            params.put(name, value);
        }

        public String getSessionAttribute(String name) {
            return sessionAttributes.get(name);
        }

        public void putSessionAttribute(String name, String value) {
            sessionAttributes.put(name, value);
        }

        public void compare (RequestDescriptor request) {
            Map<String, String> base;
            Map<String, String> cmp;
            base = request.getRequestInfo();
            cmp = this.getRequestInfo();
            for (String name: base.keySet()) {
                Assert.assertEquals("Request info " + name, base.get(name), cmp.get(name));
            }
            base = request.getContextInitParameters();
            cmp = this.getContextInitParameters();
            for (String name: base.keySet()) {
                Assert.assertEquals("Context parameter " + name, base.get(name), cmp.get(name));
            }
            base = request.getContextAttributes();
            cmp = this.getContextAttributes();
            for (String name: base.keySet()) {
                Assert.assertEquals("Context attribute " + name, base.get(name), cmp.get(name));
            }
            base = request.getHeaders();
            cmp = this.getHeaders();
            for (String name: base.keySet()) {
                Assert.assertEquals("Header " + name, base.get(name), cmp.get(name));
            }
            base = request.getAttributes();
            cmp = this.getAttributes();
            for (String name: base.keySet()) {
                Assert.assertEquals("Attribute " + name, base.get(name), cmp.get(name));
            }
            base = request.getParams();
            cmp = this.getParams();
            for (String name: base.keySet()) {
                Assert.assertEquals("Param " + name, base.get(name), cmp.get(name));
            }
            base = request.getSessionAttributes();
            cmp = this.getSessionAttributes();
            for (String name: base.keySet()) {
                Assert.assertEquals("Session attribute " + name, base.get(name), cmp.get(name));
            }
        }
    }


    public static final class SnoopResult {

        public static RequestDescriptor parse(String body) {

            int n;
            int m;
            String key;
            String value;
            String name;

            RequestDescriptor request = new RequestDescriptor();

            for (String line: body.split(System.lineSeparator())) {
                n = line.indexOf(": ");
                if (n > 0) {
                    key = line.substring(0, n);
                    value = line.substring(n + 2);
                    m = key.indexOf(':');
                    if (m > 0) {
                        name = key.substring(m + 1);
                        key = key.substring(0, m);
                        if (key.equals("CONTEXT-PARAM")) {
                            request.putContextInitParameter(name, value);
                        } else if (key.equals("CONTEXT-ATTRIBUTE")) {
                            request.putContextAttribute(name, value);
                        } else if (key.equals("HEADER")) {
                            request.putHeader(name, value);
                        } else if (key.equals("ATTRIBUTE")) {
                            request.putAttribute(name, value);
                        } else if (key.equals("PARAM")) {
                            request.putParam(name, value);
                        } else if (key.equals("SESSION-ATTRIBUTE")) {
                            request.putSessionAttribute(name, value);
                        } else {
                            request.putRequestInfo(key + ":" + name, value);
                        }
                    } else {
                        request.putRequestInfo(key, value);
                    }
                }
            }

            return request;
        }
    }

    /**
     * Simple servlet that dumps request information. Tests using this should
     * note that additional information may be added to in the future and should
     * therefore test return values using SnoopResult.
     */
    public static final class SnoopServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @SuppressWarnings("deprecation")
        @Override
        public void service(HttpServletRequest request,
                            HttpServletResponse response)
                throws ServletException, IOException {

            String name;
            StringBuilder value;
            Object attribute;

            response.setContentType("text/plain");
            response.setCharacterEncoding("UTF-8");

            ServletContext ctx = this.getServletContext();
            HttpSession session = request.getSession(false);
            PrintWriter out = response.getWriter();

            out.println("CONTEXT-NAME: " + ctx.getServletContextName());
            out.println("CONTEXT-PATH: " + ctx.getContextPath());
            out.println("CONTEXT-MAJOR-VERSION: " + ctx.getMajorVersion());
            out.println("CONTEXT-MINOR-VERSION: " + ctx.getMinorVersion());
            out.println("CONTEXT-SERVER-INFO: " + ctx.getServerInfo());
            for (Enumeration<String> e = ctx.getInitParameterNames();
                 e.hasMoreElements();) {
                name = e.nextElement();
                out.println("CONTEXT-INIT-PARAM:" + name + ": " +
                            ctx.getInitParameter(name));
            }
            for (Enumeration<String> e = ctx.getAttributeNames();
                 e.hasMoreElements();) {
                name = e.nextElement();
                out.println("CONTEXT-ATTRIBUTE:" + name + ": " +
                            ctx.getAttribute(name));
            }
            out.println("REQUEST-CONTEXT-PATH: " + request.getContextPath());
            out.println("REQUEST-SERVER-NAME: " + request.getServerName());
            out.println("REQUEST-SERVER-PORT: " + request.getServerPort());
            out.println("REQUEST-LOCAL-NAME: " + request.getLocalName());
            out.println("REQUEST-LOCAL-ADDR: " + request.getLocalAddr());
            out.println("REQUEST-LOCAL-PORT: " + request.getLocalPort());
            out.println("REQUEST-REMOTE-HOST: " + request.getRemoteHost());
            out.println("REQUEST-REMOTE-ADDR: " + request.getRemoteAddr());
            out.println("REQUEST-REMOTE-PORT: " + request.getRemotePort());
            out.println("REQUEST-PROTOCOL: " + request.getProtocol());
            out.println("REQUEST-SCHEME: " + request.getScheme());
            out.println("REQUEST-IS-SECURE: " + request.isSecure());
            out.println("REQUEST-URI: " + request.getRequestURI());
            out.println("REQUEST-URL: " + request.getRequestURL());
            out.println("REQUEST-SERVLET-PATH: " + request.getServletPath());
            out.println("REQUEST-METHOD: " + request.getMethod());
            out.println("REQUEST-PATH-INFO: " + request.getPathInfo());
            out.println("REQUEST-PATH-TRANSLATED: " +
                        request.getPathTranslated());
            out.println("REQUEST-QUERY-STRING: " + request.getQueryString());
            out.println("REQUEST-REMOTE-USER: " + request.getRemoteUser());
            out.println("REQUEST-AUTH-TYPE: " + request.getAuthType());
            out.println("REQUEST-USER-PRINCIPAL: " +
                        request.getUserPrincipal());
            out.println("REQUEST-CHARACTER-ENCODING: " +
                        request.getCharacterEncoding());
            out.println("REQUEST-CONTENT-LENGTH: " +
                        request.getContentLengthLong());
            out.println("REQUEST-CONTENT-TYPE: " + request.getContentType());
            out.println("REQUEST-LOCALE: " + request.getLocale());

            for (Enumeration<String> e = request.getHeaderNames();
                 e.hasMoreElements();) {
                name = e.nextElement();
                value = new StringBuilder();
                for (Enumeration<String> h = request.getHeaders(name);
                     h.hasMoreElements();) {
                    value.append(h.nextElement());
                    if (h.hasMoreElements()) {
                        value.append(";");
                    }
                }
                out.println("HEADER:" + name + ": " + value);
            }

            for (Enumeration<String> e = request.getAttributeNames();
                 e.hasMoreElements();) {
                name = e.nextElement();
                attribute = request.getAttribute(name);
                out.println("ATTRIBUTE:" + name + ": " +
                            (attribute != null ? attribute : "(null)"));
            }

            for (Enumeration<String> e = request.getParameterNames();
                 e.hasMoreElements();) {
                name = e.nextElement();
                value = new StringBuilder();
                String values[] = request.getParameterValues(name);
                int m = values.length;
                for (int j = 0; j < m; j++) {
                    value.append(values[j]);
                    if (j < m - 1) {
                        value.append(";");
                    }
                }
                out.println("PARAM/" + name + ": " + value);
            }

            out.println("SESSION-REQUESTED-ID: " +
                        request.getRequestedSessionId());
            out.println("SESSION-REQUESTED-ID-COOKIE: " +
                        request.isRequestedSessionIdFromCookie());
            out.println("SESSION-REQUESTED-ID-URL: " +
                        request.isRequestedSessionIdFromUrl());
            out.println("SESSION-REQUESTED-ID-VALID: " +
                        request.isRequestedSessionIdValid());

            if (session != null) {
                out.println("SESSION-ID: " + session.getId());
                out.println("SESSION-CREATION-TIME: " +
                        session.getCreationTime());
                out.println("SESSION-LAST-ACCESSED-TIME: " +
                        session.getLastAccessedTime());
                out.println("SESSION-MAX-INACTIVE-INTERVAL: " +
                        session.getMaxInactiveInterval());
                out.println("SESSION-IS-NEW: " + session.isNew());
                for (Enumeration<String> e = session.getAttributeNames();
                     e.hasMoreElements();) {
                    name = e.nextElement();
                    attribute = session.getAttribute(name);
                    out.println("SESSION-ATTRIBUTE:" + name + ": " +
                                (attribute != null ? attribute : "(null)"));
                }
            }

            int bodySize = 0;
            if ("PUT".equalsIgnoreCase(request.getMethod())) {
                InputStream is = request.getInputStream();
                int read = 0;
                byte[] buffer = new byte[8192];
                while (read != -1) {
                    read = is.read(buffer);
                    if (read > -1) {
                        bodySize += read;
                    }
                }
            }
            out.println("REQUEST-BODY-SIZE: " + bodySize);
        }
    }


    /**
     * Servlet that simply echos the request body back as the response body.
     */
    public static class EchoBodyServlet extends HttpServlet {

        private static final long serialVersionUID = 1L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            // NO-OP - No body to echo
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            // Beware of clients that try to send the whole request body before
            // reading any of the response. They may cause this test to lock up.
            try (InputStream is = req.getInputStream();
                    OutputStream os = resp.getOutputStream()) {
                IOTools.flow(is, os);
            }
        }
    }


    /*
     *  Wrapper for getting the response.
     */
    public static ByteChunk getUrl(String path) throws IOException {
        ByteChunk out = new ByteChunk();
        getUrl(path, out, null);
        return out;
    }

    public static int getUrl(String path, ByteChunk out,
            Map<String, List<String>> resHead) throws IOException {
        return getUrl(path, out, null, resHead);
    }

    public static int headUrl(String path, ByteChunk out,
            Map<String, List<String>> resHead) throws IOException {
        return methodUrl(path, out, 1000000, null, resHead, "HEAD");
    }

    public static int getUrl(String path, ByteChunk out,
            Map<String, List<String>> reqHead,
            Map<String, List<String>> resHead) throws IOException {
        return getUrl(path, out, 1000000, reqHead, resHead);
    }

    public static int getUrl(String path, ByteChunk out, int readTimeout,
            Map<String, List<String>> reqHead,
            Map<String, List<String>> resHead) throws IOException {
        return methodUrl(path, out, readTimeout, reqHead, resHead, "GET");
    }

    public static int methodUrl(String path, ByteChunk out, int readTimeout,
            Map<String, List<String>> reqHead,
            Map<String, List<String>> resHead,
            String method) throws IOException {

        URL url = new URL(path);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setUseCaches(false);
        connection.setReadTimeout(readTimeout);
        connection.setRequestMethod(method);
        if (reqHead != null) {
            for (Map.Entry<String, List<String>> entry : reqHead.entrySet()) {
                StringBuilder valueList = new StringBuilder();
                for (String value : entry.getValue()) {
                    if (valueList.length() > 0) {
                        valueList.append(',');
                    }
                    valueList.append(value);
                }
                connection.setRequestProperty(entry.getKey(),
                        valueList.toString());
            }
        }
        connection.connect();
        int rc = connection.getResponseCode();
        if (resHead != null) {
            Map<String, List<String>> head = connection.getHeaderFields();
            resHead.putAll(head);
        }
        InputStream is;
        if (rc < 400) {
            is = connection.getInputStream();
        } else {
            is = connection.getErrorStream();
        }
        if (is != null) {
            try (BufferedInputStream bis = new BufferedInputStream(is)) {
                byte[] buf = new byte[2048];
                int rd = 0;
                while((rd = bis.read(buf)) > 0) {
                    out.append(buf, 0, rd);
                }
            }
        }
        return rc;
    }

    public static ByteChunk postUrl(byte[] body, String path)
            throws IOException {
        ByteChunk out = new ByteChunk();
        postUrl(body, path, out, null);
        return out;
    }

    public static int postUrl(byte[] body, String path, ByteChunk out,
            Map<String, List<String>> resHead) throws IOException {
        return postUrl(body, path, out, null, resHead);
    }

    public static int postUrl(final byte[] body, String path, ByteChunk out,
            Map<String, List<String>> reqHead,
            Map<String, List<String>> resHead) throws IOException {
            BytesStreamer s = new BytesStreamer() {
            boolean done = false;
            @Override
            public byte[] next() {
                done = true;
                return body;

            }

            @Override
            public int getLength() {
                return body!=null?body.length:0;
            }

            @Override
            public int available() {
                if (done) return 0;
                else return getLength();
            }
        };
        return postUrl(false,s,path,out,reqHead,resHead);
    }


    public static int postUrl(boolean stream, BytesStreamer streamer, String path, ByteChunk out,
                Map<String, List<String>> reqHead,
                Map<String, List<String>> resHead) throws IOException {

        URL url = new URL(path);
        HttpURLConnection connection =
            (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setReadTimeout(1000000);
        if (reqHead != null) {
            for (Map.Entry<String, List<String>> entry : reqHead.entrySet()) {
                StringBuilder valueList = new StringBuilder();
                for (String value : entry.getValue()) {
                    if (valueList.length() > 0) {
                        valueList.append(',');
                    }
                    valueList.append(value);
                }
                connection.setRequestProperty(entry.getKey(),
                        valueList.toString());
            }
        }
        if (streamer != null && stream) {
            if (streamer.getLength()>0) {
                connection.setFixedLengthStreamingMode(streamer.getLength());
            } else {
                connection.setChunkedStreamingMode(1024);
            }
        }

        connection.connect();

        // Write the request body
        try (OutputStream os = connection.getOutputStream()) {
            while (streamer != null && streamer.available() > 0) {
                byte[] next = streamer.next();
                os.write(next);
                os.flush();
            }
        } catch (IOException ioe) {
            // Failed to write the request body. Server may have closed the
            // connection.
            ioe.printStackTrace();
        }

        int rc = connection.getResponseCode();
        if (resHead != null) {
            Map<String, List<String>> head = connection.getHeaderFields();
            resHead.putAll(head);
        }
        InputStream is;
        if (rc < 400) {
            is = connection.getInputStream();
        } else {
            is = connection.getErrorStream();
        }

        try (BufferedInputStream bis = new BufferedInputStream(is)) {
            byte[] buf = new byte[2048];
            int rd = 0;
            while((rd = bis.read(buf)) > 0) {
                out.append(buf, 0, rd);
            }
        }
        return rc;
    }

    protected static String getStatusCode(String statusLine) {
        if (statusLine == null || statusLine.length() < 12) {
            return statusLine;
        } else {
            return statusLine.substring(9, 12);
        }
    }

    private static class TomcatWithFastSessionIDs extends Tomcat {

        @Override
        public void start() throws LifecycleException {
            // Use fast, insecure session ID generation for all tests
            Server server = getServer();
            for (Service service : server.findServices()) {
                @SuppressWarnings("deprecation")
                Container e = service.getContainer();
                for (Container h : e.findChildren()) {
                    for (Container c : h.findChildren()) {
                        Manager m = ((Context) c).getManager();
                        if (m == null) {
                            m = new StandardManager();
                            ((Context) c).setManager(m);
                        }
                        if (m instanceof ManagerBase) {
                            ((ManagerBase) m).setSecureRandomClass(
                                    "org.apache.catalina.startup.FastNonSecureRandom");
                        }
                    }
                }
            }
            super.start();
        }
    }


    public static void recursiveCopy(final Path src, final Path dest)
            throws IOException {

        Files.walkFileTree(src, new FileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir,
                    BasicFileAttributes attrs) throws IOException {
                Files.copy(dir, dest.resolve(src.relativize(dir)));
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file,
                    BasicFileAttributes attrs) throws IOException {
                Path destPath = dest.resolve(src.relativize(file));
                Files.copy(file, destPath);
                // Make sure that HostConfig thinks all newly copied files have
                // been modified.
                destPath.toFile().setLastModified(
                        System.currentTimeMillis() - 2 * HostConfig.FILE_MODIFICATION_RESOLUTION_MS);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException ioe)
                    throws IOException {
                throw ioe;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException ioe)
                    throws IOException {
                // NO-OP
                return FileVisitResult.CONTINUE;
            }});
    }
}
