Path: blob/master/test/jdk/java/net/URLConnection/ContentHandlers/ContentHandlersTest.java
41153 views
/*1* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.BufferedReader;24import java.io.BufferedWriter;25import java.io.File;26import java.io.FileReader;27import java.io.FileWriter;28import java.io.IOException;29import java.io.InputStream;30import java.io.InputStreamReader;31import java.io.Reader;32import java.io.SequenceInputStream;33import java.io.StringWriter;34import java.io.Writer;35import java.nio.file.Files;36import java.nio.file.Path;37import java.nio.file.Paths;38import java.util.ArrayList;39import java.util.Arrays;40import java.util.Collection;41import java.util.Collections;42import java.util.Iterator;43import java.util.List;44import java.util.Map;45import java.util.function.Function;46import java.util.stream.Collectors;47import java.util.stream.Stream;4849import static java.lang.String.format;50import static java.util.Arrays.asList;51import static java.util.Collections.emptyMap;52import static java.util.Collections.singleton;53import static java.util.Collections.singletonMap;5455/*56* @test57* @bug 806492558* @summary Basic test for ContentHandler. Ensures discovery paths for content59* handlers follow a particular order.60*/61public class ContentHandlersTest {6263public static void main(String[] args) throws Throwable {64step1_ContentHandlerFactory();65step2_ServiceLoader();66step3_UserDefined();67step4_BuiltIn();68}6970private static void step1_ContentHandlerFactory() throws IOException {71String factoryClassFqn = "net.java.openjdk.test.TestContentHandlerFactory";7273Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-1"));7475Path src = templatesHome().resolve("test.template");76Path dst = tmp.resolve("Test.java");77Files.copy(src, dst);7879Path build = Files.createDirectory(tmp.resolve("build"));8081Path dst1 = fromTemplate(templatesHome().resolve("broken_factory.template"),82factoryClassFqn, tmp);8384javac(build, dst, dst1);8586Result r = java(emptyMap(), singleton(build), "Test", factoryClassFqn);8788if (r.exitValue == 0 || !r.output.startsWith(89stackTraceStringForBrokenFactory(factoryClassFqn))) {90throw new RuntimeException(91"Expected a different kind of failure: " + r.output);92}93}9495private static void step2_ServiceLoader() throws IOException {96String factoryClassFqn = "net.java.openjdk.test.TestContentHandlerFactory";9798Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-2"));99100Path src = templatesHome().resolve("test.template");101Path dst = tmp.resolve("Test.java");102Files.copy(src, dst);103104Path dst1 = fromTemplate(templatesHome().resolve("broken_constructor_factory.template"),105factoryClassFqn, tmp);106107Path build = Files.createDirectory(tmp.resolve("build"));108109javac(build, dst);110111Path explodedJar = Files.createDirectory(tmp.resolve("exploded-jar"));112Path services = Files.createDirectories(explodedJar.resolve("META-INF")113.resolve("services"));114115Path s = services.resolve("java.net.ContentHandlerFactory");116117try (FileWriter fw = new FileWriter(s.toFile())) {118fw.write(factoryClassFqn);119}120121javac(explodedJar, dst1);122jar(tmp.resolve("test.jar"), explodedJar);123124Files.copy(tmp.resolve("test.jar"), build.resolve("test.jar"));125126Result r = java(emptyMap(), asList(build.resolve("test.jar"), build), "Test");127128if (r.exitValue == 0 || !verifyOutput(r.output, factoryClassFqn))129throw new RuntimeException(r.output);130}131132private static void step3_UserDefined() throws IOException {133String packagePrefix = "net.java.openjdk.test";134String fqn = packagePrefix + ".text.plain";135136Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-3"));137138Path src = templatesHome().resolve("test.template");139Path dst = tmp.resolve("Test.java");140Files.copy(src, dst);141142Path dst1 = fromTemplate(templatesHome().resolve("plain.template"),143fqn, tmp);144145Path build = Files.createDirectory(tmp.resolve("build"));146147javac(build, dst);148149Path classes = Files.createDirectory(tmp.resolve("classes"));150151javac(classes, dst1);152153Map<String, String> m = singletonMap("java.content.handler.pkgs", packagePrefix);154Result r = java(m, asList(build, classes), "Test");155156if (r.exitValue != 0 || !r.output.contains(fqn))157throw new RuntimeException(r.output);158}159160private static void step4_BuiltIn() throws IOException {161Path tmp = Files.createDirectory(Paths.get("ContentHandlersTest-4"));162163Path src = templatesHome().resolve("test.template");164Path dst = tmp.resolve("Test.java");165Files.copy(src, dst);166167Path build = Files.createDirectory(tmp.resolve("build"));168169javac(build, dst);170171Result r = java(emptyMap(), singleton(build), "Test");172173if (r.exitValue != 0 || !r.output.contains("sun.net.www.content.text.PlainTextInputStream"))174throw new RuntimeException(r.output);175}176177private static String stackTraceStringForBrokenFactory(String fqn) {178return "Exception in thread \"main\" java.lang.RuntimeException: " +179"This is a broken factory. It is supposed to throw this exception.";180}181182private static Path fromTemplate(Path srcTemplate,183String factoryFqn,184Path dstFolder) throws IOException {185186String factorySimpleName, packageName;187int i = factoryFqn.lastIndexOf('.');188if (i < 0) {189packageName = "";190factorySimpleName = factoryFqn;191} else {192packageName = factoryFqn.substring(0, i);193factorySimpleName = factoryFqn.substring(i + 1);194}195196Path result = dstFolder.resolve(factorySimpleName + ".java");197File dst = result.toFile();198File src = srcTemplate.toFile();199try (BufferedReader r = new BufferedReader(new FileReader(src));200BufferedWriter w = new BufferedWriter(new FileWriter(dst))) {201202List<String> lines = processTemplate(packageName, factorySimpleName,203r.lines()).collect(Collectors.toList());204205Iterator<String> it = lines.iterator();206if (it.hasNext())207w.write(it.next());208while (it.hasNext()) {209w.newLine();210w.write(it.next());211}212}213return result;214}215216private static Stream<String> processTemplate(String packageName,217String factorySimpleName,218Stream<String> lines) {219Function<String, String> pckg;220221if (packageName.isEmpty()) {222pckg = s -> s.contains("$package") ? "" : s;223} else {224pckg = s -> s.replaceAll("\\$package", packageName);225}226227Function<String, String> factory228= s -> s.replaceAll("\\$className", factorySimpleName);229230return lines.map(pckg).map(factory);231}232233// IMO, that's the easiest way that gives you a fair amount of confidence in234// that j.u.ServiceLoader is loading a factory rather than Class.forName235private static boolean verifyOutput(String output, String fqn) {236String s1 = String.format("java.util.ServiceConfigurationError: " +237"java.net.ContentHandlerFactory: " +238"Provider %s could not be instantiated", fqn);239240return output.contains(s1);241}242243private static void jar(Path jarName, Path jarRoot) {244String jar = getJDKTool("jar");245ProcessBuilder p = new ProcessBuilder(jar, "cf", jarName.toString(),246"-C", jarRoot.toString(), ".");247quickFail(run(p));248}249250private static void javac(Path compilationOutput, Path... sourceFiles) {251String javac = getJDKTool("javac");252List<String> commands = new ArrayList<>();253commands.addAll(asList(javac, "-d", compilationOutput.toString()));254List<Path> paths = asList(sourceFiles);255commands.addAll(paths.stream()256.map(Path::toString)257.collect(Collectors.toList()));258quickFail(run(new ProcessBuilder(commands)));259}260261private static void quickFail(Result r) {262if (r.exitValue != 0)263throw new RuntimeException(r.output);264}265266private static Result java(Map<String, String> properties,267Collection<Path> classpath,268String classname, String... args) {269270String java = getJDKTool("java");271272List<String> commands = new ArrayList<>();273commands.add(java);274commands.addAll(properties.entrySet()275.stream()276.map(e -> "-D" + e.getKey() + "=" + e.getValue())277.collect(Collectors.toList()));278279String cp = classpath.stream()280.map(Path::toString)281.collect(Collectors.joining(File.pathSeparator));282commands.add("-cp");283commands.add(cp);284commands.add(classname);285commands.addAll(Arrays.asList(args));286287return run(new ProcessBuilder(commands));288}289290private static Result run(ProcessBuilder b) {291Process p;292try {293p = b.start();294} catch (IOException e) {295throw new RuntimeException(296format("Couldn't start process '%s'", b.command()), e);297}298299String output;300try {301output = toString(p.getInputStream(), p.getErrorStream());302} catch (IOException e) {303throw new RuntimeException(304format("Couldn't read process output '%s'", b.command()), e);305}306307try {308p.waitFor();309} catch (InterruptedException e) {310throw new RuntimeException(311format("Process hasn't finished '%s'", b.command()), e);312}313314return new Result(p.exitValue(), output);315}316317private static String getJDKTool(String name) {318String testJdk = System.getProperty("test.jdk");319if (testJdk == null)320throw new RuntimeException("Please provide test.jdk property at a startup");321return testJdk + File.separator + "bin" + File.separator + name;322}323324private static Path templatesHome() {325String testSrc = System.getProperty("test.src");326if (testSrc == null)327throw new RuntimeException("Please provide test.src property at a startup");328return Paths.get(testSrc);329}330331private static String toString(InputStream... src) throws IOException {332StringWriter dst = new StringWriter();333Reader concatenated =334new InputStreamReader(335new SequenceInputStream(336Collections.enumeration(asList(src))));337copy(concatenated, dst);338return dst.toString();339}340341private static void copy(Reader src, Writer dst) throws IOException {342int len;343char[] buf = new char[1024];344try {345while ((len = src.read(buf)) != -1)346dst.write(buf, 0, len);347} finally {348try {349src.close();350} catch (IOException ignored1) {351} finally {352try {353dst.close();354} catch (IOException ignored2) {355}356}357}358}359360private static class Result {361362final int exitValue;363final String output;364365private Result(int exitValue, String output) {366this.exitValue = exitValue;367this.output = output;368}369}370}371372373