/*
 * Copyright (c) 2015, 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 jdk.test.lib.process.ProcessTools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.SequenceInputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonMap;

/*
 * @test
 * @bug 8064925
 * @library /test/lib
 * @summary Basic test for ContentHandler. Ensures discovery paths for content
 *          handlers follow a particular order.
 */
public class ContentHandlersTest {

    public static void main(String[] args) throws Throwable {
        step1_ContentHandlerFactory();
        step2_ServiceLoader();
        step3_UserDefined();
        step4_BuiltIn();
    }

    private static void step1_ContentHandlerFactory() throws IOException {
        String factoryClassFqn = "net.java.openjdk.test.TestContentHandlerFactory";

        Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-1"));

        Path src = templatesHome().resolve("test.template");
        Path dst = tmp.resolve("Test.java");
        Files.copy(src, dst);

        Path build = Files.createDirectory(tmp.resolve("build"));

        Path dst1 = fromTemplate(templatesHome().resolve("broken_factory.template"),
                factoryClassFqn, tmp);

        javac(build, dst, dst1);

        Result r = java(emptyMap(), singleton(build), "Test", factoryClassFqn);

        if (r.exitValue == 0 || !r.output.startsWith(
                stackTraceStringForBrokenFactory(factoryClassFqn))) {
            throw new RuntimeException(
                    "Expected a different kind of failure: " + r.output);
        }
    }

    private static void step2_ServiceLoader() throws IOException {
        String factoryClassFqn = "net.java.openjdk.test.TestContentHandlerFactory";

        Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-2"));

        Path src = templatesHome().resolve("test.template");
        Path dst = tmp.resolve("Test.java");
        Files.copy(src, dst);

        Path dst1 = fromTemplate(templatesHome().resolve("broken_constructor_factory.template"),
                factoryClassFqn, tmp);

        Path build = Files.createDirectory(tmp.resolve("build"));

        javac(build, dst);

        Path explodedJar = Files.createDirectory(tmp.resolve("exploded-jar"));
        Path services = Files.createDirectories(explodedJar.resolve("META-INF")
                .resolve("services"));

        Path s = services.resolve("java.net.ContentHandlerFactory");

        try (FileWriter fw = new FileWriter(s.toFile())) {
            fw.write(factoryClassFqn);
        }

        javac(explodedJar, dst1);
        jar(tmp.resolve("test.jar"), explodedJar);

        Files.copy(tmp.resolve("test.jar"), build.resolve("test.jar"));

        Result r = java(emptyMap(), asList(build.resolve("test.jar"), build), "Test");

        if (r.exitValue == 0 || !verifyOutput(r.output, factoryClassFqn))
            throw new RuntimeException(r.output);
    }

    private static void step3_UserDefined() throws IOException {
        String packagePrefix = "net.java.openjdk.test";
        String fqn = packagePrefix + ".text.plain";

        Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-3"));

        Path src = templatesHome().resolve("test.template");
        Path dst = tmp.resolve("Test.java");
        Files.copy(src, dst);

        Path dst1 = fromTemplate(templatesHome().resolve("plain.template"),
                fqn, tmp);

        Path build = Files.createDirectory(tmp.resolve("build"));

        javac(build, dst);

        Path classes = Files.createDirectory(tmp.resolve("classes"));

        javac(classes, dst1);

        Map<String, String> m = singletonMap("java.content.handler.pkgs", packagePrefix);
        Result r = java(m, asList(build, classes), "Test");

        if (r.exitValue != 0 || !r.output.contains(fqn))
            throw new RuntimeException(r.output);
    }

    private static void step4_BuiltIn() throws IOException {
        Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-4"));

        Path src = templatesHome().resolve("test.template");
        Path dst = tmp.resolve("Test.java");
        Files.copy(src, dst);

        Path build = Files.createDirectory(tmp.resolve("build"));

        javac(build, dst);

        Result r = java(emptyMap(), singleton(build), "Test");

        if (r.exitValue != 0 || !r.output.contains("sun.net.www.content.text.PlainTextInputStream"))
            throw new RuntimeException(r.output);
    }

    private static String stackTraceStringForBrokenFactory(String fqn) {
        return "Exception in thread \"main\" java.lang.RuntimeException: " +
                "This is a broken factory. It is supposed to throw this exception.";
    }

    private static Path fromTemplate(Path srcTemplate,
                                     String factoryFqn,
                                     Path dstFolder) throws IOException {

        String factorySimpleName, packageName;
        int i = factoryFqn.lastIndexOf('.');
        if (i < 0) {
            packageName = "";
            factorySimpleName = factoryFqn;
        } else {
            packageName = factoryFqn.substring(0, i);
            factorySimpleName = factoryFqn.substring(i + 1);
        }

        Path result = dstFolder.resolve(factorySimpleName + ".java");
        File dst = result.toFile();
        File src = srcTemplate.toFile();
        try (BufferedReader r = new BufferedReader(new FileReader(src));
             BufferedWriter w = new BufferedWriter(new FileWriter(dst))) {

            List<String> lines = processTemplate(packageName, factorySimpleName,
                    r.lines()).collect(Collectors.toList());

            Iterator<String> it = lines.iterator();
            if (it.hasNext())
                w.write(it.next());
            while (it.hasNext()) {
                w.newLine();
                w.write(it.next());
            }
        }
        return result;
    }

    private static Stream<String> processTemplate(String packageName,
                                                  String factorySimpleName,
                                                  Stream<String> lines) {
        Function<String, String> pckg;

        if (packageName.isEmpty()) {
            pckg = s -> s.contains("$package") ? "" : s;
        } else {
            pckg = s -> s.replaceAll("\\$package", packageName);
        }

        Function<String, String> factory
                = s -> s.replaceAll("\\$className", factorySimpleName);

        return lines.map(pckg).map(factory);
    }

    // IMO, that's the easiest way that gives you a fair amount of confidence in
    // that j.u.ServiceLoader is loading a factory rather than Class.forName
    private static boolean verifyOutput(String output, String fqn) {
        String s1 = String.format("java.util.ServiceConfigurationError: " +
                "java.net.ContentHandlerFactory: " +
                "Provider %s could not be instantiated", fqn);

        return output.contains(s1);
    }

    private static void jar(Path jarName, Path jarRoot) {
        String jar = getJDKTool("jar");
        ProcessBuilder p = new ProcessBuilder(jar, "cf", jarName.toString(),
                "-C", jarRoot.toString(), ".");
        quickFail(run(p));
    }

    private static void javac(Path compilationOutput, Path... sourceFiles) {
        String javac = getJDKTool("javac");
        List<String> commands = new ArrayList<>();
        commands.addAll(asList(javac, "-d", compilationOutput.toString()));
        List<Path> paths = asList(sourceFiles);
        commands.addAll(paths.stream()
                .map(Path::toString)
                .collect(Collectors.toList()));
        quickFail(run(new ProcessBuilder(commands)));
    }

    private static void quickFail(Result r) {
        if (r.exitValue != 0)
            throw new RuntimeException(r.output);
    }

    private static Result java(Map<String, String> properties,
                               Collection<Path> classpath,
                               String classname, String... args) {

        List<String> commands = properties.entrySet()
                .stream()
                .map(e -> "-D" + e.getKey() + "=" + e.getValue())
                .collect(Collectors.toList());

        String cp = classpath.stream()
                .map(Path::toString)
                .collect(Collectors.joining(File.pathSeparator));
        commands.add("-cp");
        commands.add(cp);
        commands.add(classname);
        commands.addAll(Arrays.asList(args));

        return run(ProcessTools.createTestJavaProcessBuilder(commands));
    }

    private static Result run(ProcessBuilder b) {
        Process p;
        try {
            p = b.start();
        } catch (IOException e) {
            throw new RuntimeException(
                    format("Couldn't start process '%s'", b.command()), e);
        }

        String output;
        try {
            output = toString(p.getInputStream(), p.getErrorStream());
        } catch (IOException e) {
            throw new RuntimeException(
                    format("Couldn't read process output '%s'", b.command()), e);
        }

        try {
            p.waitFor();
        } catch (InterruptedException e) {
            throw new RuntimeException(
                    format("Process hasn't finished '%s'", b.command()), e);
        }

        return new Result(p.exitValue(), output);
    }

    private static String getJDKTool(String name) {
        String testJdk = System.getProperty("test.jdk");
        if (testJdk == null)
            throw new RuntimeException("Please provide test.jdk property at a startup");
        return testJdk + File.separator + "bin" + File.separator + name;
    }

    private static Path templatesHome() {
        String testSrc = System.getProperty("test.src");
        if (testSrc == null)
            throw new RuntimeException("Please provide test.src property at a startup");
        return Paths.get(testSrc);
    }

    private static String toString(InputStream... src) throws IOException {
        StringWriter dst = new StringWriter();
        Reader concatenated =
                new InputStreamReader(
                        new SequenceInputStream(
                                Collections.enumeration(asList(src))));
        copy(concatenated, dst);
        return dst.toString();
    }

    private static void copy(Reader src, Writer dst) throws IOException {
        int len;
        char[] buf = new char[1024];
        try {
            while ((len = src.read(buf)) != -1)
                dst.write(buf, 0, len);
        } finally {
            try {
                src.close();
            } catch (IOException ignored1) {
            } finally {
                try {
                    dst.close();
                } catch (IOException ignored2) {
                }
            }
        }
    }

    private static class Result {

        final int exitValue;
        final String output;

        private Result(int exitValue, String output) {
            this.exitValue = exitValue;
            this.output = output;
        }
    }
}
