--- old/src/java.base/share/classes/java/util/spi/ToolProvider.java 2016-10-11 11:00:21.000000000 -0700 +++ new/src/java.base/share/classes/java/util/spi/ToolProvider.java 2016-10-11 11:00:20.000000000 -0700 @@ -56,8 +56,8 @@ /** * Returns the name of this tool provider. * - * @apiNote It is recommended that the name be the same as would be used on - * the command line: for example, "javac", "jar", "jlink". + * @apiNote It is recommended that the name be the same as would be + * used on the command line: for example, "javac", "jar", "jlink". * * @return the name of this tool provider */ @@ -67,12 +67,13 @@ * Runs an instance of the tool, returning zero for a successful run. * Any non-zero return value indicates a tool-specific error during the * execution. + * * Two streams should be provided, for "expected" output, and for any * error messages. If it is not necessary to distinguish the output, * the same stream may be used for both. * * @apiNote The interpretation of the arguments will be specific to - * each tool. + * each tool. * * @param out a stream to which "expected" output should be written * @@ -81,12 +82,13 @@ * @param args the command-line arguments for the tool * * @return the result of executing the tool. - * A return value of 0 means the tool did not encounter any errors; - * any other value indicates that at least one error occurred during - * execution. + * A return value of 0 means the tool did not encounter any errors; + * any other value indicates that at least one error occurred + * during execution. * * @throws NullPointerException if any of the arguments are {@code null}, - * or if there are any {@code null} values in the {@code args} array + * or if there are any {@code null} values in the {@code args} + * array */ int run(PrintWriter out, PrintWriter err, String... args); @@ -94,16 +96,17 @@ * Runs an instance of the tool, returning zero for a successful run. * Any non-zero return value indicates a tool-specific error during the * execution. + * * Two streams should be provided, for "expected" output, and for any * error messages. If it is not necessary to distinguish the output, * the same stream may be used for both. * * @apiNote The interpretation of the arguments will be specific to - * each tool. + * each tool. * * @implNote This implementation wraps the {@code out} and {@code err} - * streams within {@link PrintWriter}s, and then calls - * {@link run(PrintWriter, PrintWriter, String[])}. + * streams within {@link PrintWriter}s, and then calls + * {@link #run(PrintWriter, PrintWriter, String[])}. * * @param out a stream to which "expected" output should be written * @@ -112,12 +115,13 @@ * @param args the command-line arguments for the tool * * @return the result of executing the tool. - * A return value of 0 means the tool did not encounter any errors; - * any other value indicates that at least one error occurred during - * execution. + * A return value of 0 means the tool did not encounter any errors; + * any other value indicates that at least one error occurred + * during execution. * * @throws NullPointerException if any of the arguments are {@code null}, - * or if there are any {@code null} values in the {@code args} array + * or if there are any {@code null} values in the {@code args} + * array */ default int run(PrintStream out, PrintStream err, String... args) { Objects.requireNonNull(out); --- old/src/jdk.jartool/share/classes/module-info.java 2016-10-11 11:00:22.000000000 -0700 +++ new/src/jdk.jartool/share/classes/module-info.java 2016-10-11 11:00:21.000000000 -0700 @@ -26,5 +26,7 @@ module jdk.jartool { exports com.sun.jarsigner; exports jdk.security.jarsigner; + + provides java.util.spi.ToolProvider with sun.tools.jar.JarToolProvider; } --- old/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java 2016-10-11 11:00:22.000000000 -0700 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java 2016-10-11 11:00:22.000000000 -0700 @@ -27,6 +27,7 @@ import java.io.File; import java.io.PrintStream; +import java.io.PrintWriter; import java.lang.module.ModuleFinder; import java.lang.module.ModuleDescriptor.Version; import java.nio.file.Path; @@ -289,7 +290,7 @@ throw new BadArgs("error.unrecognized.option", name).showUsage(true); } - static void printHelp(PrintStream out) { + static void printHelp(PrintWriter out) { out.format("%s%n", Main.getMsg("main.help.preopt")); for (OptionType type : OptionType.values()) { boolean typeHeadingWritten = false; @@ -312,16 +313,16 @@ out.format("%n%s%n%n", Main.getMsg("main.help.postopt")); } - static void printCompatHelp(PrintStream out) { + static void printCompatHelp(PrintWriter out) { out.format("%s%n", Main.getMsg("usage.compat")); } - static void printUsageSummary(PrintStream out) { + static void printUsageSummary(PrintWriter out) { out.format("%s%n", Main.getMsg("main.usage.summary")); out.format("%s%n", Main.getMsg("main.usage.summary.try")); } - static void printVersion(PrintStream out) { + static void printVersion(PrintWriter out) { out.format("%s %s%n", "jar", System.getProperty("java.version")); } } --- old/src/jdk.jartool/share/classes/sun/tools/jar/Main.java 2016-10-11 11:00:23.000000000 -0700 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/Main.java 2016-10-11 11:00:23.000000000 -0700 @@ -76,7 +76,7 @@ public class Main { String program; - PrintStream out, err; + PrintWriter out, err; String fname, mname, ename; String zname = ""; String rootjar = null; @@ -189,9 +189,9 @@ USAGE_SUMMARY(GNUStyleOptions::printUsageSummary), VERSION(GNUStyleOptions::printVersion); - private Consumer printFunction; - Info(Consumer f) { this.printFunction = f; } - void print(PrintStream out) { printFunction.accept(out); } + private Consumer printFunction; + Info(Consumer f) { this.printFunction = f; } + void print(PrintWriter out) { printFunction.accept(out); } }; Info info; @@ -252,6 +252,12 @@ } public Main(PrintStream out, PrintStream err, String program) { + this.out = new PrintWriter(out, true); + this.err = new PrintWriter(err, true); + this.program = program; + } + + public Main(PrintWriter out, PrintWriter err, String program) { this.out = out; this.err = err; this.program = program; --- old/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java 2016-10-11 11:00:24.000000000 -0700 +++ new/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java 2016-10-11 11:00:24.000000000 -0700 @@ -153,7 +153,7 @@ = taskHelper.newOptionsHelper(JlinkTask.class, recognizedOptions); private PrintWriter log; - void setLog(PrintWriter out) { + void setLog(PrintWriter out, PrintWriter err) { log = out; taskHelper.setLog(log); } @@ -182,7 +182,8 @@ int run(String[] args) { if (log == null) { - setLog(new PrintWriter(System.out, true)); + setLog(new PrintWriter(System.out, true), + new PrintWriter(System.err, true)); } try { optionsHelper.handleOptions(this, args); --- old/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java 2016-10-11 11:00:25.000000000 -0700 +++ new/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java 2016-10-11 11:00:25.000000000 -0700 @@ -26,6 +26,7 @@ package jdk.tools.jlink.internal; import java.io.*; +import java.util.spi.ToolProvider; public class Main { public static void main(String... args) throws Exception { @@ -34,17 +35,27 @@ System.exit(rc); } - /** * Entry point that does not call System.exit. * - * @param args command line arguments * @param out output stream + * @param err error output stream + * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - public static int run(String[] args, PrintWriter out) { + public static int run(PrintWriter out, PrintWriter err, String... args) { JlinkTask t = new JlinkTask(); - t.setLog(out); + t.setLog(out, err); return t.run(args); } + + public static class JlinkToolProvider implements ToolProvider { + public String name() { + return "jlink"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(out, err, args); + } + } } --- old/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java 2016-10-11 11:00:26.000000000 -0700 +++ new/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java 2016-10-11 11:00:26.000000000 -0700 @@ -32,6 +32,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.io.PrintWriter; import java.io.UncheckedIOException; import java.lang.module.Configuration; import java.lang.module.ModuleReader; @@ -136,8 +137,8 @@ private static final String MODULE_INFO = "module-info.class"; private Options options; - private PrintStream out = System.out; - void setLog(PrintStream out) { + private PrintWriter out = new PrintWriter(System.out, true); + void setLog(PrintWriter out, PrintWriter err) { this.out = out; } --- old/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java 2016-10-11 11:00:27.000000000 -0700 +++ new/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java 2016-10-11 11:00:27.000000000 -0700 @@ -26,6 +26,7 @@ package jdk.tools.jmod; import java.io.*; +import java.util.spi.ToolProvider; public class Main { public static void main(String... args) throws Exception { @@ -37,13 +38,24 @@ /** * Entry point that does not call System.exit. * - * @param args command line arguments * @param out output stream + * @param err error output stream + * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - public static int run(String[] args, PrintStream out) { + public static int run(PrintWriter out, PrintWriter err, String... args) { JmodTask t = new JmodTask(); - t.setLog(out); + t.setLog(out, err); return t.run(args); } + + public static class JmodToolProvider implements ToolProvider { + public String name() { + return "jmod"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(out, err, args); + } + } } --- old/src/jdk.jlink/share/classes/module-info.java 2016-10-11 11:00:28.000000000 -0700 +++ new/src/jdk.jlink/share/classes/module-info.java 2016-10-11 11:00:28.000000000 -0700 @@ -31,6 +31,9 @@ uses jdk.tools.jlink.plugin.Plugin; + provides java.util.spi.ToolProvider with jdk.tools.jmod.Main.JmodToolProvider; + provides java.util.spi.ToolProvider with jdk.tools.jlink.internal.Main.JlinkToolProvider; + provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludePlugin; --- old/test/java/lang/module/ModuleReader/ModuleReaderTest.java 2016-10-11 11:00:29.000000000 -0700 +++ new/test/java/lang/module/ModuleReader/ModuleReaderTest.java 2016-10-11 11:00:28.000000000 -0700 @@ -25,8 +25,8 @@ * @test * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jmod * jdk.compiler + * jdk.jlink * @build ModuleReaderTest CompilerUtils JarUtils * @run testng ModuleReaderTest * @summary Basic tests for java.lang.module.ModuleReader @@ -48,6 +48,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.Optional; +import java.util.spi.ToolProvider; import jdk.internal.module.ConfigurableModuleFinder; import jdk.internal.module.ConfigurableModuleFinder.Phase; @@ -196,8 +197,8 @@ String cp = MODS_DIR.resolve(TEST_MODULE).toString(); String jmod = dir.resolve("m.jmod").toString(); String[] args = { "create", "--class-path", cp, jmod }; - jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask(); - assertEquals(task.run(args), 0); + ToolProvider jmodTool = ToolProvider.findFirst("jmod").get(); + assertEquals(jmodTool.run(System.out, System.out, args), 0); test(dir); } --- old/test/tools/jar/ChangeDir.java 2016-10-11 11:00:29.000000000 -0700 +++ new/test/tools/jar/ChangeDir.java 2016-10-11 11:00:29.000000000 -0700 @@ -24,7 +24,7 @@ /** * @test * @bug 4806786 8023113 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar -C doesn't ignore multiple // in path */ @@ -32,10 +32,13 @@ import java.nio.file.*; import java.util.*; import java.util.jar.*; +import java.util.spi.ToolProvider; import java.util.stream.Stream; -import sun.tools.jar.Main; public class ChangeDir { + private static final ToolProvider JAR_TOOL = + ToolProvider.findFirst("jar").get(); + private final static String jarName = "test.jar"; private final static String fileName = "hello.txt"; @@ -88,8 +91,9 @@ argList.add(topDir.toString() + sep + "a" + sep + sep + "b"); // Note double 'sep' is intentional argList.add(fileName); - Main jarTool = new Main(System.out, System.err, "jar"); - if (!jarTool.run(argList.toArray(new String[argList.size()]))) { + int rc = JAR_TOOL.run(System.out, System.err, + argList.toArray(new String[argList.size()])); + if (rc != 0) { fail("Could not create jar file."); } --- old/test/tools/jar/InputFilesTest.java 2016-10-11 11:00:30.000000000 -0700 +++ new/test/tools/jar/InputFilesTest.java 2016-10-11 11:00:30.000000000 -0700 @@ -29,7 +29,7 @@ * duplicates that sometimes cause exceptions and other times do not, * demonstrating identical behavior to JDK 8 jar tool. * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @build jdk.testlibrary.FileUtils * @run testng InputFilesTest */ @@ -47,12 +47,16 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import java.util.zip.ZipException; import jdk.testlibrary.FileUtils; public class InputFilesTest { + private static final ToolProvider JAR_TOOL = + ToolProvider.findFirst("jar").get(); + private final String nl = System.lineSeparator(); private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); private final PrintStream out = new PrintStream(baos); @@ -195,9 +199,9 @@ PrintStream err = new PrintStream(baes); PrintStream saveErr = System.err; System.setErr(err); - boolean ok = new sun.tools.jar.Main(out, err, "jar").run(cmdline.split(" +")); + int rc = JAR_TOOL.run(out, err, cmdline.split(" +")); System.setErr(saveErr); - if (!ok) { + if (rc != 0) { String s = baes.toString(); if (s.startsWith("java.util.zip.ZipException: duplicate entry: ")) { throw new ZipException(s); --- old/test/tools/jar/JarBackSlash.java 2016-10-11 11:00:31.000000000 -0700 +++ new/test/tools/jar/JarBackSlash.java 2016-10-11 11:00:31.000000000 -0700 @@ -28,7 +28,7 @@ /* * @test * @bug 7201156 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar tool fails to convert file separation characters for list and extract * @author Sean Chou */ @@ -43,10 +43,11 @@ import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; - -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class JarBackSlash { + private static final ToolProvider JAR_TOOL = + ToolProvider.findFirst("jar").get(); // used construct an entry JarBackSlash/dir/file.txt private static String JARBACKSLASH = "JarBackSlash"; @@ -78,8 +79,8 @@ PipedInputStream pipedInput = new PipedInputStream(pipedOutput); PrintStream out = new PrintStream(pipedOutput); - Main jarTool = new Main(out, System.err, "jar"); - if (!jarTool.run(jarArgs)) { + int rc = JAR_TOOL.run(out, System.err, jarArgs); + if (rc != 0) { fail("Could not list jar file."); } --- old/test/tools/jar/JarEntryTime.java 2016-10-11 11:00:32.000000000 -0700 +++ new/test/tools/jar/JarEntryTime.java 2016-10-11 11:00:32.000000000 -0700 @@ -24,7 +24,7 @@ /** * @test * @bug 4225317 6969651 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Check extracted files have date as per those in the .jar file */ @@ -33,9 +33,11 @@ import java.nio.file.attribute.FileTime; import java.util.Date; import java.util.TimeZone; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class JarEntryTime { + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").get(); + // ZipEntry's mod date has 2 seconds precision: give extra time to // allow for e.g. rounding/truncation and networked/samba drives. @@ -114,10 +116,8 @@ check(fileInner.setLastModified(earlier)); // Make a jar file from that directory structure - Main jartool = new Main(System.out, System.err, "jar"); - check(jartool.run(new String[] { - "cf", - jarFile.getName(), dirOuter.getName() } )); + check(JAR_TOOL.run(System.out, System.err, + "cf", jarFile.getName(), dirOuter.getName()) == 0); check(jarFile.exists()); check(cleanup(dirInner)); @@ -142,7 +142,6 @@ final long start = testFile.lastModified(); // Extract and check the last modified values are the current times. - // See sun.tools.jar.Main extractJar(jarFile, true); try (PrintWriter pw = new PrintWriter(testFile)) { --- old/test/tools/jar/UpdateJar.java 2016-10-11 11:00:33.000000000 -0700 +++ new/test/tools/jar/UpdateJar.java 2016-10-11 11:00:32.000000000 -0700 @@ -24,7 +24,7 @@ /** * @test * @bug 7175845 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar -uf should not change file permission */ @@ -32,9 +32,11 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.util.Set; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class UpdateJar { + private static final ToolProvider JAR_TOOL = + ToolProvider.findFirst("jar").get(); private static void cleanup(String... fnames) throws Throwable { for (String fname : fnames) { @@ -55,12 +57,12 @@ fos1.write(0); } String[] jarArgs = new String[] {"cfM0", jar, e0}; - if (!new Main(System.out, System.err, "jar").run(jarArgs)) { + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { fail("Could not create jar file."); } Set pm = Files.getPosixFilePermissions(Paths.get(jar)); jarArgs = new String[] {"uf", jar, e1}; - if (!new Main(System.out, System.err, "jar").run(jarArgs)) { + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { fail("Could not create jar file."); } equal(pm, Files.getPosixFilePermissions(Paths.get(jar))); --- old/test/tools/jar/UpdateManifest.java 2016-10-11 11:00:34.000000000 -0700 +++ new/test/tools/jar/UpdateManifest.java 2016-10-11 11:00:34.000000000 -0700 @@ -24,7 +24,7 @@ /** * @test * @bug 6434207 6442687 6984046 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Ensure that jar ufm actually updates the * existing jar file's manifest with contents of the * manifest file. @@ -32,14 +32,16 @@ import java.io.*; import java.util.logging.*; +import java.util.spi.ToolProvider; import java.util.zip.*; -import sun.tools.jar.Main; public class UpdateManifest { static PrintStream out = System.out; static PrintStream err = System.err; static boolean debug = true; + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").get(); + static final Logger JAR_LOGGER = Logger.getLogger("java.util.jar"); public static void realMain(String[] args) throws Throwable { @@ -64,17 +66,14 @@ // Create a jar file, specifying a Main-Class final String jarFileName = "um-existence.jar"; new File(jarFileName).delete(); // remove pre-existing first! - Main jartool = new Main(out, err, "jar"); - boolean status = jartool.run( - new String[] { "cfe", jarFileName, "Hello", existence.getPath() }); - check(status); + int status = JAR_TOOL.run(out, err, "cfe", jarFileName, + "Hello", existence.getPath()); + check(status == 0); checkManifest(jarFileName, "Hello"); // Update that jar file by changing the Main-Class - jartool = new Main(out, err, "jar"); - status = jartool.run( - new String[] { "ufe", jarFileName, "Bye" }); - check(status); + status = JAR_TOOL.run(out, err, "ufe", jarFileName, "Bye"); + check(status == 0); checkManifest(jarFileName, "Bye"); } @@ -101,11 +100,9 @@ // Create a jar file final String jarFileName = "um-test.jar"; new File(jarFileName).delete(); // remove pre-existing first! - Main jartool = new Main(out, err, "jar"); - boolean status = jartool.run( - new String[] {"cfm", jarFileName, - manifestOrig.getPath(), hello.getPath() }); - check(status); + int status = JAR_TOOL.run(out, err, "cfm", jarFileName, + manifestOrig.getPath(), hello.getPath()); + check(status == 0); // Create a new manifest, to use in updating the jar file. File manifestUpdate = File.createTempFile("manifestUpdate", ".txt"); @@ -122,10 +119,9 @@ pw.close(); // Update jar file with manifest - jartool = new Main(out, err, "jar"); - status = jartool.run( - new String[] { "ufm", jarFileName, manifestUpdate.getPath() }); - check(status); + status = JAR_TOOL.run(out, err, "ufm", + jarFileName, manifestUpdate.getPath()); + check(status == 0); // Extract jar, and verify contents of manifest file File f = new File(jarFileName); --- old/test/tools/jar/index/MetaInf.java 2016-10-11 11:00:35.000000000 -0700 +++ new/test/tools/jar/index/MetaInf.java 2016-10-11 11:00:35.000000000 -0700 @@ -24,17 +24,18 @@ /* * @test * @bug 4408526 6854795 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Index the non-meta files in META-INF, such as META-INF/services. */ import java.io.*; import java.util.Arrays; import java.util.jar.*; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; import java.util.zip.ZipFile; public class MetaInf { + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").get(); static String jarName = "a.jar"; static String INDEX = "META-INF/INDEX.LIST"; @@ -43,7 +44,7 @@ System.getProperty("test.src") + File.separatorChar + "jarcontents"; static void run(String ... args) { - if (! new Main(System.out, System.err, "jar").run(args)) + if (JAR_TOOL.run(System.out, System.err, args) != 0) throw new Error("jar failed: args=" + Arrays.toString(args)); } --- old/test/tools/jlink/JLinkTest.java 2016-10-11 11:00:36.000000000 -0700 +++ new/test/tools/jlink/JLinkTest.java 2016-10-11 11:00:35.000000000 -0700 @@ -32,13 +32,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.internal.PluginRepository; import tests.Helper; import tests.JImageGenerator; -import tests.JImageGenerator.InMemoryFile; /* * @test @@ -48,13 +48,14 @@ * @modules java.base/jdk.internal.jimage * jdk.jdeps/com.sun.tools.classfile * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod * jdk.jlink/jdk.tools.jimage * jdk.compiler * @build tests.* * @run main/othervm -Xmx1g JLinkTest */ public class JLinkTest { + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink").get(); + // number of built-in plugins from jdk.jlink module private static int getNumJlinkPlugins() { ModuleDescriptor desc = Plugin.class.getModule().getDescriptor(); @@ -180,7 +181,8 @@ { // Help StringWriter writer = new StringWriter(); - jdk.tools.jlink.internal.Main.run(new String[]{"--help"}, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + JLINK_TOOL.run(pw, pw, "--help"); String output = writer.toString(); if (output.split("\n").length < 10) { System.err.println(output); @@ -202,7 +204,9 @@ { // List plugins StringWriter writer = new StringWriter(); - jdk.tools.jlink.internal.Main.run(new String[]{"--list-plugins"}, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + + JLINK_TOOL.run(pw, pw, "--list-plugins"); String output = writer.toString(); long number = Stream.of(output.split("\\R")) .filter((s) -> s.matches("Plugin Name:.*")) --- old/test/tools/jlink/basic/BasicTest.java 2016-10-11 11:00:36.000000000 -0700 +++ new/test/tools/jlink/basic/BasicTest.java 2016-10-11 11:00:36.000000000 -0700 @@ -27,8 +27,7 @@ * @author Andrei Eremeev * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod + * jdk.jlink * jdk.compiler * @build jdk.testlibrary.ProcessTools * jdk.testlibrary.OutputAnalyzer @@ -44,11 +43,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.spi.ToolProvider; import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.ProcessTools; public class BasicTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod").get(); + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink").get(); private final Path jdkHome = Paths.get(System.getProperty("test.jdk")); private final Path jdkMods = jdkHome.resolve("jmods"); @@ -110,20 +112,22 @@ "--add-modules", modName, "--output", image.toString()); Collections.addAll(args, options); - int rc = jdk.tools.jlink.internal.Main.run(args.toArray(new String[args.size()]), new PrintWriter(System.out)); + + PrintWriter pw = new PrintWriter(System.out); + int rc = JLINK_TOOL.run(pw, pw, args.toArray(new String[args.size()])); if (rc != 0) { throw new AssertionError("Jlink failed: rc = " + rc); } } private void runJmod(String cp, String modName) { - int rc = jdk.tools.jmod.Main.run(new String[] { + int rc = JMOD_TOOL.run(System.out, System.out, new String[] { "create", "--class-path", cp, "--module-version", "1.0", "--main-class", "jdk.test.Test", jmods.resolve(modName + ".jmod").toString(), - }, System.out); + }); if (rc != 0) { throw new AssertionError("Jmod failed: rc = " + rc); } --- old/test/tools/jmod/JmodNegativeTest.java 2016-10-11 11:00:37.000000000 -0700 +++ new/test/tools/jmod/JmodNegativeTest.java 2016-10-11 11:00:37.000000000 -0700 @@ -24,8 +24,8 @@ /* * @test * @library /lib/testlibrary - * @modules jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodNegativeTest * @summary Negative tests for jmod @@ -39,6 +39,7 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.spi.ToolProvider; import java.util.zip.ZipOutputStream; import jdk.testlibrary.FileUtils; import org.testng.annotations.BeforeTest; @@ -51,6 +52,8 @@ public class JmodNegativeTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod").get(); + static final String TEST_SRC = System.getProperty("test.src", "."); static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); static final Path EXPLODED_DIR = Paths.get("build"); @@ -515,7 +518,7 @@ ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.out.println("jmod " + Arrays.asList(args)); - int ec = jdk.tools.jmod.Main.run(args, ps); + int ec = JMOD_TOOL.run(ps, ps, args); return new JmodResult(ec, new String(baos.toByteArray(), UTF_8)); } --- old/test/tools/jmod/JmodTest.java 2016-10-11 11:00:38.000000000 -0700 +++ new/test/tools/jmod/JmodTest.java 2016-10-11 11:00:38.000000000 -0700 @@ -24,8 +24,8 @@ /* * @test * @library /lib/testlibrary - * @modules jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodTest * @summary Basic test for jmod @@ -38,6 +38,7 @@ import java.util.*; import java.util.function.Consumer; import java.util.regex.Pattern; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.testlibrary.FileUtils; import org.testng.annotations.BeforeTest; @@ -51,6 +52,8 @@ public class JmodTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod").get(); + static final String TEST_SRC = System.getProperty("test.src", "."); static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); static final Path EXPLODED_DIR = Paths.get("build"); @@ -479,7 +482,7 @@ ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.out.println("jmod " + Arrays.asList(args)); - int ec = jdk.tools.jmod.Main.run(args, ps); + int ec = JMOD_TOOL.run(ps, ps, args); return new JmodResult(ec, new String(baos.toByteArray(), UTF_8)); } --- old/test/tools/jmod/hashes/HashesTest.java 2016-10-11 11:00:39.000000000 -0700 +++ new/test/tools/jmod/hashes/HashesTest.java 2016-10-11 11:00:39.000000000 -0700 @@ -27,8 +27,7 @@ * @author Andrei Eremeev * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod + * jdk.jlink * jdk.compiler * @build CompilerUtils * @run testng HashesTest @@ -53,6 +52,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.spi.ToolProvider; import java.util.stream.Collectors; import jdk.internal.module.ConfigurableModuleFinder; @@ -63,6 +63,7 @@ import static org.testng.Assert.*; public class HashesTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod").get(); private final Path testSrc = Paths.get(System.getProperty("test.src")); private final Path modSrc = testSrc.resolve("src"); @@ -204,7 +205,7 @@ } private void runJmod(List args) { - int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out); + int rc = JMOD_TOOL.run(System.out, System.out, args.toArray(new String[args.size()])); System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" "))); if (rc != 0) { throw new AssertionError("Jmod failed: rc = " + rc); --- old/test/tools/launcher/modules/basic/BasicTest.java 2016-10-11 11:00:40.000000000 -0700 +++ new/test/tools/launcher/modules/basic/BasicTest.java 2016-10-11 11:00:39.000000000 -0700 @@ -24,9 +24,9 @@ /** * @test * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar - * jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jartool + * jdk.jlink * @build BasicTest CompilerUtils jdk.testlibrary.* * @run testng BasicTest * @summary Basic test of starting an application as a module @@ -36,6 +36,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.spi.ToolProvider; import jdk.testlibrary.ProcessTools; @@ -46,6 +47,8 @@ @Test public class BasicTest { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").get(); + private static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod").get(); private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); @@ -132,10 +135,8 @@ "--main-class=" + MAIN_CLASS, "-C", classes, "." }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar") - .run(args); - assertTrue(success); + int rc = JAR_TOOL.run(System.out, System.out, args); + assertTrue(rc == 0); // java --module-path mlib -module $TESTMODULE int exitValue = exec("--module-path", dir.toString(), @@ -164,8 +165,8 @@ "--main-class", MAIN_CLASS, jmod }; - jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask(); - assertEquals(task.run(args), 0); + + assertEquals(JMOD_TOOL.run(System.out, System.out, args), 0); // java --module-path mods --module $TESTMODULE int exitValue = exec("--module-path", dir.toString(), @@ -229,10 +230,8 @@ "--file=" + jar, "-C", classes, "." }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar") - .run(args); - assertTrue(success); + int rc = JAR_TOOL.run(System.out, System.out, args); + assertTrue(rc == 0); // java --module-path mods -m $TESTMODULE int exitValue = exec("--module-path", dir.toString(), "-m", TEST_MODULE); --- old/test/tools/launcher/modules/dryrun/DryRunTest.java 2016-10-11 11:00:40.000000000 -0700 +++ new/test/tools/launcher/modules/dryrun/DryRunTest.java 2016-10-11 11:00:40.000000000 -0700 @@ -26,7 +26,7 @@ * @bug 8159596 * @library /lib/testlibrary * @modules jdk.compiler - * jdk.jartool/sun.tools.jar + * jdk.jartool * @build DryRunTest CompilerUtils jdk.testlibrary.ProcessTools * @run testng DryRunTest * @summary Test java --dry-run @@ -37,6 +37,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.spi.ToolProvider; import jdk.testlibrary.ProcessTools; @@ -78,8 +79,8 @@ Files.createDirectories(LIBS_DIR); // create JAR files with no module-info.class - assertTrue(jar(M_MODULE, "p/Lib.class")); - assertTrue(jar(TEST_MODULE, "jdk/test/Main.class")); + assertTrue(jar(M_MODULE, "p/Lib.class") == 0); + assertTrue(jar(TEST_MODULE, "jdk/test/Main.class") == 0); } /** @@ -197,7 +198,9 @@ assertTrue(exitValue != 0); } - private static boolean jar(String name, String entries) throws IOException { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar").get(); + + private static int jar(String name, String entries) throws IOException { Path jar = LIBS_DIR.resolve(name + ".jar"); // jar --create ... @@ -207,8 +210,6 @@ "--file=" + jar, "-C", classes, entries }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar").run(args); - return success; + return JAR_TOOL.run(System.out, System.out, args); } } --- old/test/tools/lib/tests/JImageGenerator.java 2016-10-11 11:00:41.000000000 -0700 +++ new/test/tools/lib/tests/JImageGenerator.java 2016-10-11 11:00:41.000000000 -0700 @@ -338,6 +338,8 @@ } public static class JModTask { + static final java.util.spi.ToolProvider JMOD_TOOL = + java.util.spi.ToolProvider.findFirst("jmod").get(); private final List classpath = new ArrayList<>(); private final List libs = new ArrayList<>(); @@ -477,7 +479,8 @@ String[] args = optionsJMod(cmd); System.err.println("jmod options: " + optionsPrettyPrint(args)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int exitCode = jdk.tools.jmod.Main.run(args, new PrintStream(baos)); + PrintStream ps = new PrintStream(baos); + int exitCode = JMOD_TOOL.run(ps, ps, args); String msg = new String(baos.toByteArray()); return new Result(exitCode, msg, output); } @@ -556,6 +559,8 @@ } public static class JLinkTask { + static final java.util.spi.ToolProvider JLINK_TOOL = + java.util.spi.ToolProvider.findFirst("jlink").get(); private final List jars = new ArrayList<>(); private final List jmods = new ArrayList<>(); @@ -691,7 +696,8 @@ String[] args = optionsJLink(); System.err.println("jlink options: " + optionsPrettyPrint(args)); StringWriter writer = new StringWriter(); - int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + int exitCode = JLINK_TOOL.run(pw, pw, args); return new Result(exitCode, writer.toString(), output); } @@ -699,7 +705,8 @@ String[] args = optionsPostProcessJLink(); System.err.println("jlink options: " + optionsPrettyPrint(args)); StringWriter writer = new StringWriter(); - int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + int exitCode = JLINK_TOOL.run(pw, pw, args); return new Result(exitCode, writer.toString(), output); } } --- /dev/null 2016-10-11 11:00:42.000000000 -0700 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java 2016-10-11 11:00:42.000000000 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.tools.jar; + +import java.io.PrintWriter; +import java.util.spi.ToolProvider; + +public class JarToolProvider implements ToolProvider { + public String name() { + return "jar"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + boolean ok = new Main(out, err, name()).run(args); + return ok ? 0 : 1; + } +}