/*
 * 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.URI;
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.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

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

import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Manager;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.Session;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.connector.Connector;
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.util.collections.CaseInsensitiveKeyMap;
import org.apache.tomcat.util.http.Method;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.util.scan.StandardJarScanFilter;
import org.apache.tomcat.util.scan.StandardJarScanner;

/**
 * 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 {

    // Used by parameterized tests. Defined here to reduce duplication.
    protected static final Boolean[] booleans = new Boolean[] { Boolean.FALSE, Boolean.TRUE };

    protected static final int DEFAULT_CLIENT_TIMEOUT_MS = 300_000;

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

    private Tomcat tomcat;
    private boolean accessLogEnabled = false;

    /**
     * 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());

        StandardJarScanner scanner = (StandardJarScanner) ctx.getJarScanner();
        StandardJarScanFilter filter = (StandardJarScanFilter) scanner.getJarScanFilter();
        filter.setTldSkip(filter.getTldSkip() + ",testclasses");
        filter.setPluggabilitySkip(filter.getPluggabilitySkip() + ",testclasses");

        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;
    }


    public Context getProgrammaticRootContext() {
        // No file system docBase required
        Context ctx = tomcat.addContext("", null);
        // Disable class path scanning - it slows the tests down by almost an order of magnitude
        ((StandardJarScanner) ctx.getJarScanner()).setScanClassPath(false);
        return ctx;
    }
    public Context getProgrammaticRootContextWithManager() {
        Context ctx = getProgrammaticRootContext();
        if (ctx.getManager() == null) {
            ctx.setManager(new StandardManager());
        }
        return ctx;
    }
    /*
     * 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()) {
            Assert.fail("Unable to create appBase for test");
        }

        tomcat = new TomcatWithFastSessionIDs();

        String protocol = getProtocol();
        Connector connector = new Connector(protocol);
        // Listen only on localhost
        Assert.assertTrue(connector.setProperty("address", InetAddress.getByName("localhost").getHostAddress()));
        // Use random free port
        connector.setPort(0);
        // By default, a connector failure means a failed test
        connector.setThrowOnFailure(true);
        // Mainly set to reduce timeouts during async tests
        Assert.assertTrue(connector.setProperty("connectionTimeout", "3000"));
        tomcat.getService().addConnector(connector);
        tomcat.setConnector(connector);

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

        accessLogEnabled = Boolean.getBoolean("tomcat.test.accesslog");
        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;

        @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 (Method.PUT.equals(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 getUrl(String path, ByteChunk out, boolean followRedirects)
            throws IOException {
        return methodUrl(path, out, DEFAULT_CLIENT_TIMEOUT_MS, null, null, Method.GET, followRedirects);
    }

    public static int headUrl(String path, ByteChunk out, Map<String, List<String>> resHead)
            throws IOException {
        return methodUrl(path, out, DEFAULT_CLIENT_TIMEOUT_MS, null, resHead, Method.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, DEFAULT_CLIENT_TIMEOUT_MS, 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, Method.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 {
        return methodUrl(path, out, readTimeout, reqHead, resHead, method, true);
    }

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

        URL url = URI.create(path).toURL();
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setUseCaches(false);
        connection.setReadTimeout(readTimeout);
        connection.setRequestMethod(method);
        connection.setInstanceFollowRedirects(followRedirects);
        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) {
            // Skip the entry with null key that is used for the response line
            // that some Map implementations may not accept.
            for (Map.Entry<String, List<String>> entry : connection.getHeaderFields().entrySet()) {
                if (entry.getKey() != null) {
                    resHead.put(entry.getKey(), entry.getValue());
                }
            }
        }
        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 = URI.create(path).toURL();
        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();
            }
        }

        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);
        }
    }

    protected static String getSingleHeader(String header, Map<String,List<String>> headers) {
        // Assume headers is never null

        // Assume that either:
        // a) is correct since HTTP headers are case insensitive but most Map
        //    implementations are case-sensitive; or
        // b) CaseInsensitiveKeyMap or similar is used
        List<String> headerValues = headers.get(header);

        // Looking for a single header. No matches are OK
        if (headerValues == null) {
            return null;
        }

        // Found a single header - return the header value
        if (headerValues.size() == 1) {
            return headerValues.get(0);
        }

        // More than one header value is an error
        throw new IllegalStateException("Found multiple headers for [" + header + "]");
    }

    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()) {
                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.
                Assert.assertTrue("Failed to set last modified for [" + destPath + "]",
                        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;
            }});
    }


    public static void skipTldsForResourceJars(Context context) {
        StandardJarScanner scanner = (StandardJarScanner) context.getJarScanner();
        StandardJarScanFilter filter = (StandardJarScanFilter) scanner.getJarScanFilter();
        filter.setTldSkip(filter.getTldSkip() + ",resources*.jar");
    }


    public static void forceSessionMaxInactiveInterval(Context context, int newIntervalSecs) {
        Session[] sessions = context.getManager().findSessions();
        for (Session session : sessions) {
            session.setMaxInactiveInterval(newIntervalSecs);
        }
    }

    /**
     * Captures logs for the given logger names in the current ClassLoader.
     */
    public static class LogCapture implements AutoCloseable {
        protected final Level level;
        protected final String[] loggerNames;
        protected final List<LogRecord> logRecords = Collections.synchronizedList(new ArrayList<>());
        protected final Map<Logger, Level> previousLevelsOfLoggersMap = new IdentityHashMap<>();
        private volatile boolean installed = false;
        protected final Handler handler = new Handler() {
            @Override
            public void publish(LogRecord record) {
                logRecords.add(record);
            }

            @Override
            public void flush() {
            }

            @Override
            public void close() throws SecurityException {
                logRecords.clear();
            }
        };
        public LogCapture(Level level, String... loggerNames) {
            this.level = (level == null ? Level.ALL : level);
            this.loggerNames = loggerNames;
        }

        public void attach() {
            if (!installed) {
                for (String name : loggerNames) {
                    Logger logger = Logger.getLogger(name);
                    previousLevelsOfLoggersMap.put(logger, logger.getLevel());
                    logger.addHandler(handler);
                    logger.setLevel(level);
                }
                installed = true;
            }
        }

        public boolean containsText(CharSequence s) {
            for (LogRecord record : logRecords) {
                if (record.getMessage().contains(s)) {
                    return true;
                }
            }
            return false;
        }
        public boolean hasException(Class<? extends Throwable> type) {
            for (LogRecord record : logRecords) {
                Throwable t = record.getThrown();
                while (t != null) {
                    if (type.isInstance(t)) {return true;}
                    t = t.getCause();
                }
            }
            return false;
        }

        @Override
        public void close() throws Exception {
            for (Logger l : previousLevelsOfLoggersMap.keySet()) {
                try {
                    l.removeHandler(handler);
                } catch (Throwable ignore) {
                }
                try {
                    l.setLevel(previousLevelsOfLoggersMap.get(l));
                } catch (Throwable ignore) {
                }
            }
            previousLevelsOfLoggersMap.clear();
        }
    }

    public static LogCapture attachLogCapture(Level level, String... loggerNames) {
        LogCapture logCapture = new LogCapture(level, loggerNames);
        logCapture.attach();
        return logCapture;
    }

    /**
     * Captures webapp-scoped logs (e.g. ContextConfig/Digester) during the
     * CONFIGURE_START phase of a {@link Context}.
     */
    public static class WebappLogCapture extends LogCapture implements LifecycleListener {
        private String lifecycleEvent = Lifecycle.CONFIGURE_START_EVENT;
        public WebappLogCapture(String lifecycleEvent, Level level, String... loggerNames) {
            this(level, loggerNames);
            this.lifecycleEvent = lifecycleEvent;
        }
        public WebappLogCapture(Level level, String... loggerNames) {
            super(level, loggerNames);
        }

        @Override
        public void lifecycleEvent(LifecycleEvent event) {
            if (this.lifecycleEvent.equals(event.getType())) {
                this.attach();
            }
        }
    }

    /**
     * Installs a {@link WebappLogCapture} on the given {@link Context} so it runs
     * before {@link ContextConfig} during CONFIGURE_START.
     * @param ctx         the webapp context
     * @param level       level for loggers (e.g. {@code Level.ALL})
     * @param loggerNames fully-qualified logger names
     * @return the active capture
     */
    public static WebappLogCapture attachWebappLogCapture(Context ctx, Level level, String... loggerNames) {
        List<LifecycleListener> lifecycleListenersToReAdd = new ArrayList<>();
        for (LifecycleListener l : ctx.findLifecycleListeners()) {
            if (l instanceof ContextConfig) {
                lifecycleListenersToReAdd.add(l);
            }
        }
        for (LifecycleListener l : lifecycleListenersToReAdd) {
            ctx.removeLifecycleListener(l);
        }
        WebappLogCapture webappLogCapture = new WebappLogCapture(level, loggerNames);
        ctx.addLifecycleListener(webappLogCapture);
        for (LifecycleListener l : lifecycleListenersToReAdd) {
            ctx.addLifecycleListener(l);
        }
        return webappLogCapture;
    }

    /**
     * Returns the localized key in a LocalStrings.properties file.
     *
     * @param packagePath The package that contains LocalStrings.properties, e.g. 'org.apache.catalina.startup'
     * @param key           The key to find, e.g. 'versionLoggerListener.serverInfo.server.built'
     * @param locale        The locale to use, e.g. Locale.ENGLISH
     * @return The prefix before the first argument placeholder and if no placeholder, returns the whole formatted string.
     */
    public static String getKeyFromPropertiesFile(String packagePath, String key, Locale locale) {
        StringManager sm;
        if (locale != null) {
            sm = StringManager.getManager(packagePath, locale);
        } else {
            sm = StringManager.getManager(packagePath);
        }

        String formatted = sm.getString(key, "XXX");
        int insertIndex = formatted.indexOf("XXX");
        return (insertIndex == -1) ? formatted : formatted.substring(0, insertIndex);
    }
    public static String getKeyFromPropertiesFile(String packagePath, String key) {
        return getKeyFromPropertiesFile(packagePath, key, Locale.getDefault());
    }
    public static String getKeyFromPropertiesFile(StringManager sm, String key) {
        String formatted = sm.getString(key, "XXX");
        int insertIndex = formatted.indexOf("XXX");
        return (insertIndex == -1) ? formatted : formatted.substring(0, insertIndex);
    }

    /**
     * Injects a {@link LifecycleListener} to a {@link Context} of a {@link Container} that sends {@code ADD_CHILD_EVENT}.
     * Useful when deploying with the Manager / HostConfig.
     */
    public static class ContainerInjector implements ContainerListener, AutoCloseable {

        private final Container container;
        private final Predicate<Context> filter;
        private final Consumer<Context> action;
        private volatile boolean installed = false;
        private String containerEvent = Container.ADD_CHILD_EVENT;

        private ContainerInjector(Container container, Predicate<Context> filter, Consumer<Context> action, String containerEvent) {
            this.container = container;
            this.filter = filter;
            this.action = action;
            if (containerEvent != null) {
                this.containerEvent = containerEvent;
            }
            container.addContainerListener(this);
        }

        public static ContainerInjector inject(Container container, Predicate<Context> filter, Consumer<Context> action) {
            return new ContainerInjector(container, filter, action, null);
        }
        public static ContainerInjector inject(Container container, Predicate<Context> filter, Consumer<Context> action, String containerEvent) {
            return new ContainerInjector(container, filter, action, containerEvent);
        }

        @Override
        public void containerEvent(ContainerEvent event) {
            if (this.containerEvent.equals(event.getType()) && !installed) {
                Object data = event.getData();
                if (data instanceof Context ctx) {
                    if (filter != null && filter.test(ctx)) {
                        action.accept(ctx);
                        installed = true;
                    }
                }
            }
        }

        @Override
        public void close() {
            container.removeContainerListener(this);
        }
    }
}
