/*
 * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.util.FileUtils;
import sun.net.www.ParseUtil;

import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.CharBuffer;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.security.Security;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

/*
 * @test
 * @summary Tests security properties passed through java.security,
 *   java.security.properties or included from other properties files.
 * @bug 8155246 8292297 8292177 8281658 8319332
 * @modules java.base/sun.net.www
 * @library /test/lib
 * @run main ConfigFileTest
 */

public class ConfigFileTest {
    static final String SEPARATOR_THIN = "----------------------------";

    private static void printTestHeader(String testName) {
        System.out.println();
        System.out.println(SEPARATOR_THIN);
        System.out.println(testName);
        System.out.println(SEPARATOR_THIN);
        System.out.println();
    }

    public static void main(String[] args) throws Exception {
        if (args.length == 1 && Executor.RUNNER_ARG.equals(args[0])) {
            // Executed by a test-launched JVM.
            // Force the initialization of java.security.Security.
            Security.getProviders();
            Security.setProperty("postInitTest", "shouldNotRecord");
            System.out.println(FilesManager.LAST_FILE_PROP_NAME + ": " +
                    Security.getProperty(FilesManager.LAST_FILE_PROP_NAME));
            assertTestSecuritySetPropertyShouldNotInclude();
        } else {
            // Executed by the test JVM.
            try (FilesManager filesMgr = new FilesManager()) {
                for (Method m : ConfigFileTest.class.getDeclaredMethods()) {
                    if (m.getName().startsWith("test")) {
                        printTestHeader(m.getName());
                        Executor.run(m, filesMgr);
                    }
                }
            }
        }
    }

    /*
     * Success cases
     */

    static void testShowSettings(Executor ex, FilesManager filesMgr)
            throws Exception {
        // Sanity test passing the -XshowSettings:security option.
        ex.addJvmArg("-XshowSettings:security");
        ex.setMasterFile(filesMgr.newMasterFile());
        ex.assertSuccess();
        ex.getOutputAnalyzer()
                .shouldContain("Security properties:")
                .shouldContain("Security provider static configuration:")
                .shouldContain("Security TLS configuration");
    }

    static void testIncludeBasic(Executor ex, FilesManager filesMgr)
            throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        ExtraPropsFile extraFile = filesMgr.newExtraFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");
        PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
        PropsFile file2 = filesMgr.newFile("dir1/dir2/file2.properties");

        masterFile.addAbsoluteInclude(file0);
        extraFile.addRelativeInclude(file2);
        file2.addAbsoluteInclude(file1);

        ex.setMasterFile(masterFile);
        ex.setExtraFile(extraFile, Executor.ExtraMode.FILE_URI, false);
        ex.assertSuccess();
    }

    static void testRepeatedInclude(Executor ex, FilesManager filesMgr)
            throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");
        PropsFile file1 = filesMgr.newFile("dir1/file1.properties");

        masterFile.addAbsoluteInclude(file0);
        masterFile.addAbsoluteInclude(file1);
        masterFile.addAbsoluteInclude(file0);
        file1.addRelativeInclude(file0);

        ex.setMasterFile(masterFile);
        ex.assertSuccess();
    }

    static void testIncludeWithOverrideAll(Executor ex, FilesManager filesMgr)
            throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        ExtraPropsFile extraFile = filesMgr.newExtraFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");
        PropsFile file1 = filesMgr.newFile("dir1/file1.properties");

        masterFile.addRelativeInclude(file0);
        extraFile.addAbsoluteInclude(file1);

        ex.setMasterFile(masterFile);
        ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
        ex.assertSuccess();
    }

    static void extraPropertiesByHelper(Executor ex, FilesManager filesMgr,
            Executor.ExtraMode mode) throws Exception {
        ExtraPropsFile extraFile = filesMgr.newExtraFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");

        extraFile.addRelativeInclude(file0);

        ex.setMasterFile(filesMgr.newMasterFile());
        ex.setExtraFile(extraFile, mode, true);
        ex.assertSuccess();
    }

    static void testExtraPropertiesByPathAbsolute(Executor ex,
            FilesManager filesMgr) throws Exception {
        extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_ABS);
    }

    static void testExtraPropertiesByPathRelative(Executor ex,
            FilesManager filesMgr) throws Exception {
        extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_REL);
    }

    static void specialCharsIncludes(Executor ex, FilesManager filesMgr,
            char specialChar, Executor.ExtraMode extraMode,
            boolean useRelativeIncludes) throws Exception {
        String suffix = specialChar + ".properties";
        ExtraPropsFile extraFile;
        PropsFile file0, file1;
        try {
            extraFile = filesMgr.newExtraFile("extra" + suffix);
            file0 = filesMgr.newFile("file0" + suffix);
            file1 = filesMgr.newFile("file1" + suffix);
        } catch (InvalidPathException ipe) {
            // The platform encoding may not allow to create files with some
            // special characters. Skip the test in these cases.
            return;
        }

        if (useRelativeIncludes) {
            extraFile.addRelativeInclude(file0);
        } else {
            extraFile.addAbsoluteInclude(file0);
        }
        extraFile.addAbsoluteInclude(file1);

        ex.setMasterFile(filesMgr.newMasterFile());
        ex.setExtraFile(extraFile, extraMode, false);
        ex.assertSuccess();
    }

    static void testUnicodeIncludes1(Executor ex, FilesManager filesMgr)
            throws Exception {
        specialCharsIncludes(ex, filesMgr, '\u2022',
                Executor.ExtraMode.PATH_ABS, true);
    }

    static void testUnicodeIncludes2(Executor ex, FilesManager filesMgr)
            throws Exception {
        specialCharsIncludes(ex, filesMgr, '\u2022',
                Executor.ExtraMode.FILE_URI, true);
    }

    static void testUnicodeIncludes3(Executor ex, FilesManager filesMgr)
            throws Exception {
        // Backward compatibility check. Malformed URLs such as
        // file:/tmp/extra•.properties are supported for the extra file.
        // However, relative includes are not allowed in these cases.
        specialCharsIncludes(ex, filesMgr, '\u2022',
                Executor.ExtraMode.RAW_FILE_URI1, false);
    }

    static void testUnicodeIncludes4(Executor ex, FilesManager filesMgr)
            throws Exception {
        // Backward compatibility check. Malformed URLs such as
        // file:///tmp/extra•.properties are supported for the extra file.
        // However, relative includes are not allowed in these cases.
        specialCharsIncludes(ex, filesMgr, '\u2022',
                Executor.ExtraMode.RAW_FILE_URI2, false);
    }

    static void testSpaceIncludes1(Executor ex, FilesManager filesMgr)
            throws Exception {
        specialCharsIncludes(ex, filesMgr, ' ',
                Executor.ExtraMode.PATH_ABS, true);
    }

    static void testSpaceIncludes2(Executor ex, FilesManager filesMgr)
            throws Exception {
        specialCharsIncludes(ex, filesMgr, ' ',
                Executor.ExtraMode.FILE_URI, true);
    }

    static void testSpaceIncludes3(Executor ex, FilesManager filesMgr)
            throws Exception {
        // Backward compatibility check. Malformed URLs such as
        // file:/tmp/extra .properties are supported for the extra file.
        // However, relative includes are not allowed in these cases.
        specialCharsIncludes(ex, filesMgr, ' ',
                Executor.ExtraMode.RAW_FILE_URI1, false);
    }

    static void testSpaceIncludes4(Executor ex, FilesManager filesMgr)
            throws Exception {
        // Backward compatibility check. Malformed URLs such as
        // file:///tmp/extra .properties are supported for the extra file.
        // However, relative includes are not allowed in these cases.
        specialCharsIncludes(ex, filesMgr, ' ',
                Executor.ExtraMode.RAW_FILE_URI2, false);
    }

    static void notOverrideOnFailureHelper(Executor ex, FilesManager filesMgr,
            String nonExistentExtraFile) throws Exception {
        // An overriding extra properties file that does not exist
        // should not erase properties from the master file.
        ex.setIgnoredExtraFile(nonExistentExtraFile, true);
        ex.setMasterFile(filesMgr.newMasterFile());
        ex.assertSuccess();
        ex.getOutputAnalyzer().shouldContain("unable to load security " +
                "properties from " + nonExistentExtraFile);
    }

    static void testNotOverrideOnEmptyFailure(Executor ex,
            FilesManager filesMgr) throws Exception {
        notOverrideOnFailureHelper(ex, filesMgr, "");
        ex.getOutputAnalyzer()
                .shouldContain("Empty extra properties file path");
    }

    static void testNotOverrideOnURLFailure(Executor ex, FilesManager filesMgr)
            throws Exception {
        notOverrideOnFailureHelper(ex, filesMgr,
                "file:///nonExistentFile.properties");
    }

    static void testNotOverrideOnPathFailure(Executor ex, FilesManager filesMgr)
            throws Exception {
        notOverrideOnFailureHelper(ex, filesMgr, "nonExistentFile.properties");
    }

    static void testNotOverrideOnDirFailure(Executor ex, FilesManager filesMgr)
            throws Exception {
        notOverrideOnFailureHelper(ex, filesMgr, "file:///");
        ex.getOutputAnalyzer().shouldContain("Is a directory");
    }

    static void testNotOverrideOnBadFileURLFailure(Executor ex,
            FilesManager filesMgr) throws Exception {
        notOverrideOnFailureHelper(ex, filesMgr, "file:///%00");
    }

    static void testDisabledExtraPropertiesFile(Executor ex,
            FilesManager filesMgr) throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");

        masterFile.addRawProperty("security.overridePropertiesFile", "false");

        ex.setMasterFile(masterFile);
        ex.setIgnoredExtraFile(file0.path.toString(), true);
        ex.assertSuccess();
    }

    static final String SECURITY_SET_PROP_FILE_PATH =
            "testSecuritySetPropertyShouldNotInclude.propsFilePath";

    static void testSecuritySetPropertyShouldNotInclude(Executor ex,
            FilesManager filesMgr) throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");

        ex.addSystemProp(SECURITY_SET_PROP_FILE_PATH, file0.path.toString());
        ex.setMasterFile(masterFile);
        ex.assertSuccess();
    }

    static void assertTestSecuritySetPropertyShouldNotInclude() {
        // This check is executed by the launched JVM.
        String propsFilePath = System.getProperty(SECURITY_SET_PROP_FILE_PATH);
        if (propsFilePath != null) {
            String name = Path.of(propsFilePath).getFileName().toString();
            String setPropInvokeRepr = "Security.setProperty(\"include\", " +
                    "\"" + propsFilePath + "\")";
            try {
                Security.setProperty("include", propsFilePath);
                throw new RuntimeException(setPropInvokeRepr + " was " +
                        "expected to throw IllegalArgumentException.");
            } catch (IllegalArgumentException expected) {}
            if (FilesManager.APPLIED_PROP_VALUE.equals(
                    Security.getProperty(name))) {
                throw new RuntimeException(setPropInvokeRepr + " caused " +
                        "a file inclusion.");
            }
            try {
                Security.getProperty("include");
                throw new RuntimeException("Security.getProperty(\"include\")" +
                        " was expected to throw IllegalArgumentException.");
            } catch (IllegalArgumentException expected) {}
        }
    }

    /*
     * Error cases
     */

    static void testCannotResolveRelativeFromHTTPServed(Executor ex,
            FilesManager filesMgr) throws Exception {
        ExtraPropsFile extraFile = filesMgr.newExtraFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");

        extraFile.addRelativeInclude(file0);

        ex.setMasterFile(filesMgr.newMasterFile());
        ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
        ex.assertError("InternalError: Cannot resolve '" + file0.fileName +
                "' relative path when included from a non-regular " +
                "properties file (e.g. HTTP served file)");
    }

    static void testCannotIncludeCycles(Executor ex, FilesManager filesMgr)
            throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        PropsFile file0 = filesMgr.newFile("file0.properties");
        PropsFile file1 = filesMgr.newFile("dir1/file1.properties");

        // Includes chain: master -> file0 -> file1 -> master.
        file1.addRelativeInclude(masterFile);
        file0.addRelativeInclude(file1);
        masterFile.addRelativeInclude(file0);

        ex.setMasterFile(masterFile);
        ex.assertError(
                "InternalError: Cyclic include of '" + masterFile.path + "'");
    }

    static void testCannotIncludeURL(Executor ex, FilesManager filesMgr)
            throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();
        ExtraPropsFile extraFile = filesMgr.newExtraFile();

        masterFile.addRawProperty("include", extraFile.url.toString());

        ex.setMasterFile(masterFile);
        ex.assertError("InternalError: Unable to include 'http://127.0.0.1:");
    }

    static void testCannotIncludeNonexistentFile(Executor ex,
            FilesManager filesMgr) throws Exception {
        PropsFile masterFile = filesMgr.newMasterFile();

        String nonexistentPath = "/nonExistentFile.properties";
        masterFile.addRawProperty("include", nonexistentPath);

        ex.setMasterFile(masterFile);
        ex.assertError(
                "InternalError: Unable to include '" + nonexistentPath + "'");
    }

    static void testMustHaveMasterFile(Executor ex, FilesManager filesMgr)
            throws Exception {
        // Launch a JDK without a master java.security file present.
        ex.assertError("InternalError: Error loading java.security file");
    }

    static void testMustHaveMasterFileEvenWithExtraFile(Executor ex,
            FilesManager filesMgr) throws Exception {
        // Launch a JDK without a master java.security file present, but with an
        // extra file passed. Since the "security.overridePropertiesFile=true"
        // security property is missing, it should fail anyway.
        ex.setExtraFile(
                filesMgr.newExtraFile(), Executor.ExtraMode.FILE_URI, true);
        ex.assertError("InternalError: Error loading java.security file");
    }
}

sealed class PropsFile permits ExtraPropsFile {
    protected static final class Include {
        final PropsFile propsFile;
        final String value;

        private Include(PropsFile propsFile, String value) {
            this.propsFile = propsFile;
            this.value = value;
        }

        static Include of(PropsFile propsFile) {
            return new Include(propsFile, propsFile.path.toString());
        }

        static Include of(PropsFile propsFile, String value) {
            return new Include(propsFile, value);
        }
    }

    protected final List<Include> includes = new ArrayList<>();
    protected final PrintWriter writer;
    protected boolean includedFromExtra = false;
    final String fileName;
    final Path path;

    PropsFile(String fileName, Path path) throws IOException {
        this.fileName = fileName;
        this.path = path;
        this.writer = new PrintWriter(Files.newOutputStream(path,
                StandardOpenOption.CREATE, StandardOpenOption.APPEND), true);
    }

    private static String escape(String text, boolean escapeSpace) {
        StringBuilder sb = new StringBuilder(text.length());
        CharBuffer cb = CharBuffer.wrap(text);
        while (cb.hasRemaining()) {
            char c = cb.get();
            if (c == '\\' || escapeSpace && c == ' ') {
                sb.append('\\');
            }
            if (Character.UnicodeBlock.of(c) ==
                    Character.UnicodeBlock.BASIC_LATIN) {
                sb.append(c);
            } else {
                sb.append("\\u%04x".formatted((int) c));
            }
        }
        return sb.toString();
    }

    private void addRawProperty(String key, String value, String sep) {
        writer.println(escape(key, true) + sep + escape(value, false));
    }

    protected void addIncludeDefinition(Include include) {
        if (include.propsFile instanceof ExtraPropsFile) {
            throw new RuntimeException("ExtraPropsFile should not be included");
        }
        includes.add(include);
        addRawProperty("include", include.value, " ");
    }

    void addComment(String comment) {
        writer.println("# " + comment);
    }

    void addRawProperty(String key, String value) {
        addRawProperty(key, value, "=");
    }

    void addAbsoluteInclude(PropsFile propsFile) {
        addIncludeDefinition(Include.of(propsFile));
    }

    void addRelativeInclude(PropsFile propsFile) {
        addIncludeDefinition(Include.of(propsFile,
                path.getParent().relativize(propsFile.path).toString()));
    }

    void assertApplied(OutputAnalyzer oa) {
        oa.shouldContain(Executor.INITIAL_PROP_LOG_MSG + fileName + "=" +
                FilesManager.APPLIED_PROP_VALUE);
        for (Include include : includes) {
            include.propsFile.assertApplied(oa);
            oa.shouldContain("processing include: '" + include.value + "'");
            oa.shouldContain("finished processing " + include.propsFile.path);
        }
    }

    void assertWasOverwritten(OutputAnalyzer oa) {
        oa.shouldNotContain(Executor.INITIAL_PROP_LOG_MSG + fileName + "=" +
                FilesManager.APPLIED_PROP_VALUE);
        for (Include include : includes) {
            if (!include.propsFile.includedFromExtra) {
                include.propsFile.assertWasOverwritten(oa);
            }
            oa.shouldContain("processing include: '" + include.value + "'");
            oa.shouldContain("finished processing " + include.propsFile.path);
        }
    }

    void markAsIncludedFromExtra() {
        includedFromExtra = true;
        for (Include include : includes) {
            include.propsFile.markAsIncludedFromExtra();
        }
    }

    PropsFile getLastFile() {
        return includes.isEmpty() ?
                this : includes.getLast().propsFile.getLastFile();
    }

    void close() {
        writer.close();
    }
}

final class ExtraPropsFile extends PropsFile {
    private final Map<String, String> systemProps = new LinkedHashMap<>();
    final URI url;

    ExtraPropsFile(String fileName, URI url, Path path) throws IOException {
        super(fileName, path);
        this.url = url;
    }

    @Override
    protected void addIncludeDefinition(Include include) {
        if (includes.isEmpty()) {
            String propName = "props.fileName";
            systemProps.put(propName, include.propsFile.fileName);
            include = Include.of(include.propsFile,
                    include.value.replace(include.propsFile.fileName,
                            "${props.none}${" + propName + "}"));
        }
        include.propsFile.markAsIncludedFromExtra();
        super.addIncludeDefinition(include);
    }

    Map<String, String> getSystemProperties() {
        return Collections.unmodifiableMap(systemProps);
    }
}

final class FilesManager implements Closeable {
    private static final Path ROOT_DIR =
            Path.of(ConfigFileTest.class.getSimpleName()).toAbsolutePath();
    private static final Path PROPS_DIR = ROOT_DIR.resolve("properties");
    private static final Path JDK_DIR = ROOT_DIR.resolve("jdk");
    private static final Path MASTER_FILE =
            JDK_DIR.resolve("conf/security/java.security");
    private static final Path MASTER_FILE_TEMPLATE =
            MASTER_FILE.resolveSibling("java.security.template");
    static final String JAVA_EXECUTABLE =
            JDK_DIR.resolve("bin/java").toString();
    static final String LAST_FILE_PROP_NAME = "last-file";
    static final String APPLIED_PROP_VALUE = "applied";

    private final List<PropsFile> createdFiles;
    private final Set<String> fileNamesInUse;
    private final HttpServer httpServer;
    private final URI serverUri;
    private final long masterFileLines;

    FilesManager() throws Exception {
        createdFiles = new ArrayList<>();
        fileNamesInUse = new HashSet<>();
        httpServer = HttpServer.create(
                new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
        httpServer.createContext("/", this::handleRequest);
        InetSocketAddress address = httpServer.getAddress();
        httpServer.start();
        serverUri = new URI("http", null, address.getHostString(),
                address.getPort(), null, null, null);
        copyJDK();
        try (Stream<String> s = Files.lines(MASTER_FILE_TEMPLATE)) {
            masterFileLines = s.count();
        }
    }

    private static void copyJDK() throws Exception {
        Path testJDK = Path.of(Objects.requireNonNull(
                System.getProperty("test.jdk"), "unspecified test.jdk"));
        if (!Files.exists(testJDK)) {
            throw new RuntimeException("test.jdk -> nonexistent JDK");
        }
        Files.createDirectories(JDK_DIR);
        try (Stream<Path> pathStream = Files.walk(testJDK)) {
            pathStream.skip(1).forEach((Path file) -> {
                try {
                    Files.copy(file, JDK_DIR.resolve(testJDK.relativize(file)),
                            StandardCopyOption.COPY_ATTRIBUTES);
                } catch (IOException ioe) {
                    throw new UncheckedIOException(ioe);
                }
            });
        }
        Files.move(MASTER_FILE, MASTER_FILE_TEMPLATE);
    }

    private void handleRequest(HttpExchange x) throws IOException {
        String rawPath = x.getRequestURI().getRawPath();
        Path f = ROOT_DIR.resolve(x.getRequestURI().getPath().substring(1));
        int statusCode;
        byte[] responseBody;
        // Check for unescaped space, unresolved parent or backward slash.
        if (rawPath.matches("^.*( |(\\.|%2[Ee]){2}|\\\\|%5[Cc]).*$")) {
            statusCode = HttpURLConnection.HTTP_BAD_REQUEST;
            responseBody = new byte[0];
        } else if (Files.isRegularFile(f)) {
            x.getResponseHeaders().add("Content-type", "text/plain");
            statusCode = HttpURLConnection.HTTP_OK;
            responseBody = Files.readAllBytes(f);
        } else {
            statusCode = HttpURLConnection.HTTP_NOT_FOUND;
            responseBody = new byte[0];
        }
        System.out.println("[" + Instant.now() + "] " +
                getClass().getSimpleName() + ": " +
                x.getRequestMethod() + " " + rawPath + " -> " +
                statusCode + " (" + responseBody.length + " bytes)");
        try (OutputStream responseStream = x.getResponseBody()) {
            x.sendResponseHeaders(statusCode, responseBody.length);
            responseStream.write(responseBody);
        }
    }

    @FunctionalInterface
    private interface PropsFileBuilder {
        PropsFile build(String fileName, Path path) throws IOException;
    }

    private PropsFile newFile(Path path, PropsFileBuilder builder)
            throws IOException {
        String fileName = path.getFileName().toString();
        if (!fileNamesInUse.add(fileName)) {
            // Names must be unique in order for the special
            // property <fileName>=<APPLIED_PROP_VALUE> to work.
            throw new RuntimeException(fileName + " is repeated");
        }
        Files.createDirectories(path.getParent());
        PropsFile propsFile = builder.build(fileName, path);
        propsFile.addComment("Property to determine if this properties file " +
                "was parsed and not overwritten:");
        propsFile.addRawProperty(fileName, APPLIED_PROP_VALUE);
        propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
        propsFile.addComment("Property to be overwritten by every properties " +
                "file (master, extra or included):");
        propsFile.addRawProperty(LAST_FILE_PROP_NAME, fileName);
        propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
        createdFiles.add(propsFile);
        return propsFile;
    }

    PropsFile newFile(String relPathStr) throws IOException {
        return newFile(PROPS_DIR.resolve(relPathStr), PropsFile::new);
    }

    PropsFile newMasterFile() throws IOException {
        Files.copy(MASTER_FILE_TEMPLATE, MASTER_FILE);
        return newFile(MASTER_FILE, PropsFile::new);
    }

    ExtraPropsFile newExtraFile() throws IOException {
        return newExtraFile("extra.properties");
    }

    ExtraPropsFile newExtraFile(String extraFileName) throws IOException {
        return (ExtraPropsFile) newFile(PROPS_DIR.resolve(extraFileName),
                (fileName, path) -> {
                    URI uri = serverUri.resolve(ParseUtil.encodePath(
                            ROOT_DIR.relativize(path).toString()));
                    return new ExtraPropsFile(fileName, uri, path);
                });
    }

    void reportCreatedFiles() throws IOException {
        for (PropsFile propsFile : createdFiles) {
            System.err.println();
            System.err.println(propsFile.path.toString());
            System.err.println(ConfigFileTest.SEPARATOR_THIN.repeat(3));
            try (Stream<String> lines = Files.lines(propsFile.path)) {
                long lineNumber = 1L;
                Iterator<String> it = lines.iterator();
                while (it.hasNext()) {
                    String line = it.next();
                    if (!propsFile.path.equals(MASTER_FILE) ||
                            lineNumber > masterFileLines) {
                        System.err.println(line);
                    }
                    lineNumber++;
                }
            }
            System.err.println();
        }
    }

    void clear() throws IOException {
        if (!createdFiles.isEmpty()) {
            for (PropsFile propsFile : createdFiles) {
                propsFile.close();
                Files.delete(propsFile.path);
            }
            FileUtils.deleteFileTreeUnchecked(PROPS_DIR);
            createdFiles.clear();
            fileNamesInUse.clear();
        }
    }

    @Override
    public void close() throws IOException {
        clear();
        httpServer.stop(0);
        FileUtils.deleteFileTreeUnchecked(ROOT_DIR);
    }
}

final class Executor {
    enum ExtraMode {
        HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
    }
    static final String RUNNER_ARG = "runner";
    static final String INITIAL_PROP_LOG_MSG = "Initial security property: ";
    private static final String OVERRIDING_LOG_MSG =
            "overriding other security properties files!";
    private static final String[] ALWAYS_UNEXPECTED_LOG_MSGS = {
            "java.lang.AssertionError",
            INITIAL_PROP_LOG_MSG + "postInitTest=shouldNotRecord",
            INITIAL_PROP_LOG_MSG + "include=",
    };
    private static final Path CWD = Path.of(".").toAbsolutePath();
    private static final String JAVA_SEC_PROPS = "java.security.properties";
    private static final String CLASS_PATH = Objects.requireNonNull(
            System.getProperty("test.classes"), "unspecified test.classes");
    private static final String DEBUG_ARG =
            "-Xrunjdwp:transport=dt_socket,address=localhost:8000,suspend=y";
    private final Map<String, String> systemProps = new LinkedHashMap<>(
            Map.of("java.security.debug", "all", "javax.net.debug", "all",
                    // Ensure we get UTF-8 debug outputs in Windows:
                    "stderr.encoding", "UTF-8", "stdout.encoding", "UTF-8"));
    private final List<String> jvmArgs = new ArrayList<>(
            List.of(FilesManager.JAVA_EXECUTABLE, "-enablesystemassertions",
                    // Uncomment DEBUG_ARG to debug test-launched JVMs:
                    "-classpath", CLASS_PATH//, DEBUG_ARG
            ));
    private PropsFile masterPropsFile;
    private ExtraPropsFile extraPropsFile;
    private boolean expectedOverrideAll = false;
    private OutputAnalyzer oa;

    static void run(Method m, FilesManager filesMgr) throws Exception {
        try {
            m.invoke(null, new Executor(), filesMgr);
        } catch (Throwable e) {
            filesMgr.reportCreatedFiles();
            throw e;
        } finally {
            filesMgr.clear();
        }
    }

    void addSystemProp(String key, String value) {
        systemProps.put(key, value);
    }

    private void setRawExtraFile(String extraFile, boolean overrideAll) {
        addSystemProp(JAVA_SEC_PROPS, (overrideAll ? "=" : "") + extraFile);
    }

    void setMasterFile(PropsFile masterPropsFile) {
        this.masterPropsFile = masterPropsFile;
    }

    void setExtraFile(ExtraPropsFile extraPropsFile, ExtraMode mode,
            boolean overrideAll) {
        this.extraPropsFile = extraPropsFile;
        expectedOverrideAll = overrideAll;
        setRawExtraFile(switch (mode) {
            case HTTP_SERVED -> extraPropsFile.url.toString();
            case FILE_URI -> extraPropsFile.path.toUri().toString();
            case RAW_FILE_URI1 -> "file:" + extraPropsFile.path;
            case RAW_FILE_URI2 -> "file://" +
                    (extraPropsFile.path.startsWith("/") ? "" : "/") +
                    extraPropsFile.path;
            case PATH_ABS -> extraPropsFile.path.toString();
            case PATH_REL -> CWD.relativize(extraPropsFile.path).toString();
        }, overrideAll);
    }

    void setIgnoredExtraFile(String extraPropsFile, boolean overrideAll) {
        setRawExtraFile(extraPropsFile, overrideAll);
        expectedOverrideAll = false;
    }

    void addJvmArg(String arg) {
        jvmArgs.add(arg);
    }

    private void execute(boolean successExpected) throws Exception {
        List<String> command = new ArrayList<>(jvmArgs);
        Collections.addAll(command, Utils.getTestJavaOpts());
        addSystemPropertiesAsJvmArgs(command);
        command.add(ConfigFileTest.class.getSimpleName());
        command.add(RUNNER_ARG);
        oa = ProcessTools.executeProcess(new ProcessBuilder(command));
        oa.shouldHaveExitValue(successExpected ? 0 : 1);
        for (String output : ALWAYS_UNEXPECTED_LOG_MSGS) {
            oa.shouldNotContain(output);
        }
    }

    private void addSystemPropertiesAsJvmArgs(List<String> command) {
        Map<String, String> allSystemProps = new LinkedHashMap<>(systemProps);
        if (extraPropsFile != null) {
            allSystemProps.putAll(extraPropsFile.getSystemProperties());
        }
        for (Map.Entry<String, String> e : allSystemProps.entrySet()) {
            command.add("-D" + e.getKey() + "=" + e.getValue());
        }
    }

    void assertSuccess() throws Exception {
        execute(true);

        // Ensure every file was processed by checking a unique property used as
        // a flag. Each file defines <fileName>=applied.
        //
        // For example:
        //
        //   file0
        //   ---------------
        //   file0=applied
        //   include file1
        //
        //   file1
        //   ---------------
        //   file1=applied
        //
        // The assertion would be file0 == applied AND file1 == applied.
        //
        if (extraPropsFile != null) {
            extraPropsFile.assertApplied(oa);
        }
        if (expectedOverrideAll) {
            // When overriding with an extra file, check that neither
            // the master file nor its includes are visible.
            oa.shouldContain(OVERRIDING_LOG_MSG);
            masterPropsFile.assertWasOverwritten(oa);
        } else {
            oa.shouldNotContain(OVERRIDING_LOG_MSG);
            masterPropsFile.assertApplied(oa);
        }

        // Ensure the last included file overwrote a fixed property. Each file
        // defines last-file=<fileName>.
        //
        // For example:
        //
        //   file0
        //   ---------------
        //   last-file=file0
        //   include file1
        //
        //   file1
        //   ---------------
        //   last-file=file1
        //
        // The assertion would be last-file == file1.
        //
        PropsFile lastFile = (extraPropsFile == null ?
                masterPropsFile : extraPropsFile).getLastFile();
        oa.shouldContain(FilesManager.LAST_FILE_PROP_NAME + "=" +
                lastFile.fileName);
        oa.stdoutShouldContain(FilesManager.LAST_FILE_PROP_NAME + ": " +
                lastFile.fileName);
    }

    void assertError(String message) throws Exception {
        execute(false);
        oa.shouldContain(message);
    }

    OutputAnalyzer getOutputAnalyzer() {
        return oa;
    }
}
