changeset 2586:a108029dbcbf

8050429: Update/cleanup ToolBox Reviewed-by: vromero
author jjg
date Wed, 13 Aug 2014 13:20:31 -0700
parents 09bb56ec5fec
children 525e4b838572
files make/build.properties test/tools/apt/Basics/CheckAptIsRemovedTest.java test/tools/javac/4846262/CheckEBCDICLocaleTest.java test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java test/tools/javac/AnonymousSubclassTest.java test/tools/javac/ClassPathTest/ClassPathTest.java test/tools/javac/ConstFoldTest.java test/tools/javac/ExtDirs/ExtDirTest.java test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java test/tools/javac/MissingInclude/MissingIncludeTest.java test/tools/javac/Paths/AbsolutePathTest.java test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java test/tools/javac/T5090006/AssertionFailureTest.java test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java test/tools/javac/T8013394/CompileErrorWithIteratorTest.java test/tools/javac/T8019486/WrongLNTForLambdaTest.java test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java test/tools/javac/api/ToolProvider/HelloWorldTest.java test/tools/javac/api/ToolProvider/ToolProviderTest1.java test/tools/javac/api/ToolProvider/ToolProviderTest2.java test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java test/tools/javac/classfiles/attributes/SourceFile/MixTest.java test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java test/tools/javac/fatalErrors/NoJavaLangTest.java test/tools/javac/innerClassFile/InnerClassFileTest.java test/tools/javac/javazip/JavaZipTest.java test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java test/tools/javac/lib/ToolBox.java test/tools/javac/links/LinksTest.java test/tools/javac/newlines/NewLineTest.java test/tools/javac/processing/rounds/CompleteOnClosed.java test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java test/tools/javac/stackmap/StackMapTest.java test/tools/javah/6257087/T6257087.java test/tools/javah/T4942232/MissingParamClassTest.java test/tools/javah/constMacroTest/ConstMacroTest.java test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java test/tools/javap/4866831/PublicInterfaceTest.java test/tools/javap/stackmap/StackmapTest.java test/tools/lib/ToolBox.java
diffstat 54 files changed, 2576 insertions(+), 1791 deletions(-) [+]
line wrap: on
line diff
--- a/make/build.properties	Wed Aug 13 14:25:46 2014 -0400
+++ b/make/build.properties	Wed Aug 13 13:20:31 2014 -0700
@@ -68,7 +68,7 @@
 # set the following to -version to verify the versions of javac being used
 javac.version.opt =
 # in time, there should be no exceptions to -Xlint:all
-javac.lint.opts = -Xlint:all -Werror
+javac.lint.opts = -Xlint:all,-deprecation -Werror
 
 # options for the <javadoc> task for javac
 #javadoc.jls3.url=http://java.sun.com/docs/books/jls/
--- a/test/tools/apt/Basics/CheckAptIsRemovedTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/apt/Basics/CheckAptIsRemovedTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 4908512 5024825 4957203 4993280 4996963 6174696 6177059 7041249
  * @summary Make sure apt is removed and doesn't come back
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main CheckAptIsRemovedTest
  */
@@ -34,7 +34,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-//original test: test/tools/apt/Basics/apt.sh
+// Original test: test/tools/apt/Basics/apt.sh
 public class CheckAptIsRemovedTest {
     //I think this class can be let with the imports only and that should be enough for as test's purpose
     private static final String NullAPFSrc =
@@ -77,20 +77,18 @@
         Path aptLin = Paths.get(testJDK, "bin", "apt");
         Path aptWin = Paths.get(testJDK, "bin", "apt.exe");
 
-//        if [ -f "${TESTJAVA}/bin/apt" -o -f "${TESTJAVA}/bin/apt.exe" ];then
         if (Files.exists(aptLin) || Files.exists(aptWin)) {
             throw new AssertionError("apt executable should not exist");
         }
 
-//        JAVAC="${TESTJAVA}/bin/javac ${TESTTOOLVMOPTS} -source 1.5 -sourcepath ${TESTSRC} -classpath ${TESTJAVA}/lib/tools.jar -d . "
-//        $JAVAC ${TESTSRC}/NullAPF.java
         Path classpath = Paths.get(testJDK, "lib", "tools.jar");
-        ToolBox.JavaToolArgs javacArgs =
-                new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL)
-                .setOptions("-sourcepath", ".",
-                    "-classpath", classpath.toString())
-                .setSources(NullAPFSrc);
-        ToolBox.javac(javacArgs);
+        ToolBox tb = new ToolBox();
+        tb.new JavacTask()
+                .classpath(classpath.toString()) // TODO: add overload
+                .sourcepath(".")
+                .sources(NullAPFSrc)
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
     }
 
 }
--- a/test/tools/javac/4846262/CheckEBCDICLocaleTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/4846262/CheckEBCDICLocaleTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,15 +25,17 @@
  * @test
  * @bug 4846262
  * @summary check that javac operates correctly in EBCDIC locale
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main CheckEBCDICLocaleTest
  */
 
 import java.io.File;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
+import java.util.List;
 
 public class CheckEBCDICLocaleTest {
 
@@ -58,39 +60,32 @@
     }
 
     public void test() throws Exception {
-        String native2asciiBinary = Paths.get(
-                System.getProperty("test.jdk"),"bin", "native2ascii").toString();
+        ToolBox tb = new ToolBox();
+        Path native2asciiBinary = tb.getJDKTool("native2ascii");
 
-        ToolBox.createJavaFileFromSource(TestSrc);
-        Files.createDirectory(Paths.get("output"));
+        tb.writeFile("Test.java", TestSrc);
+        tb.createDirectories("output");
 
-        ToolBox.AnyToolArgs nativeCmdParams =
-                new ToolBox.AnyToolArgs()
-                .appendArgs(native2asciiBinary)
-                .appendArgs(ToolBox.testToolVMOpts)
-                .appendArgs("-reverse", "-encoding", "IBM1047", "Test.java",
-                "output/Test.java");
-        ToolBox.executeCommand(nativeCmdParams);
+        tb.new ExecTask(native2asciiBinary)
+                .args("-reverse", "-encoding", "IBM1047", "Test.java", "output/Test.java")
+                .run();
 
-        ToolBox.AnyToolArgs javacParams =
-                new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(ToolBox.javacBinary)
-                .appendArgs(ToolBox.testToolVMOpts)
-                .appendArgs("-J-Duser.language=en",
-                "-J-Duser.region=US", "-J-Dfile.encoding=IBM1047",
-                "output/Test.java")
-                .setErrOutput(new File("Test.tmp"));
-        ToolBox.executeCommand(javacParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .redirect(ToolBox.OutputKind.STDERR, "Test.tmp")
+                .options("-J-Duser.language=en",
+                        "-J-Duser.region=US",
+                        "-J-Dfile.encoding=IBM1047")
+                .files("output/Test.java")
+                .run(ToolBox.Expect.FAIL);
 
-        nativeCmdParams = new ToolBox.AnyToolArgs()
-                .appendArgs(native2asciiBinary)
-                .appendArgs(ToolBox.testToolVMOpts)
-                .appendArgs("-encoding", "IBM1047", "Test.tmp", "Test.out");
-        ToolBox.executeCommand(nativeCmdParams);
+        tb.new ExecTask(native2asciiBinary)
+                .args("-encoding", "IBM1047", "Test.tmp", "Test.out")
+                .run();
 
-        String goldenFile = String.format(TestOutTemplate, File.separator);
-        ToolBox.compareLines(Paths.get("Test.out"),
-                Arrays.asList(goldenFile.split("\n")), null, true);
+        List<String> expectLines = Arrays.asList(
+                String.format(TestOutTemplate, File.separator).split("\n"));
+        List<String> actualLines = Files.readAllLines(Paths.get("Test.out"));
+        tb.checkEqual(expectLines, actualLines);
     }
 
 }
--- a/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -26,7 +26,7 @@
  * @bug 6302184 6350124 6357979
  * @summary javac hidden options that generate source should use the given
  * encoding, if available
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run compile -encoding iso-8859-1 -XD-printsource T6302184.java
  * @run main HiddenOptionsShouldUseGivenEncodingTest
@@ -34,16 +34,19 @@
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.List;
 
-//original test: test/tools/javac/6302184/T6302184.sh
+// Original test: test/tools/javac/6302184/T6302184.sh
 public class HiddenOptionsShouldUseGivenEncodingTest {
 
     public static void main(String[] args) throws Exception {
-//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -cp ${TC} -encoding iso-8859-1 -XD-printsource ${TS}${FS}T6302184.java 2>&1
-//diff ${DIFFOPTS} -c ${TC}${FS}T6302184.java ${TS}${FS}T6302184.out
-        Path path1 = Paths.get(System.getProperty("test.classes"), "T6302184.java");
-        Path path2 = Paths.get(System.getProperty("test.src"), "T6302184.out");
-        ToolBox.compareLines(path1, path2, "iso-8859-1");
+        ToolBox tb = new ToolBox();
+        String encoding = "iso-8859-1";
+        Path path1 = Paths.get(ToolBox.testClasses, "T6302184.java");
+        List<String> file1 = tb.readAllLines(path1, encoding);
+        Path path2 = Paths.get(ToolBox.testSrc, "T6302184.out");
+        List<String> file2 = tb.readAllLines(path2, encoding);
+        tb.checkEqual(file1, file2);
     }
 
 }
--- a/test/tools/javac/AnonymousSubclassTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/AnonymousSubclassTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,19 +25,18 @@
  * @test
  * @bug 8023945
  * @summary javac wrongly allows a subclass of an anonymous class
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main AnonymousSubclassTest
  */
 
-import java.util.ArrayList;
-import java.io.IOException;
-
 public class AnonymousSubclassTest {
     public static void main(String... args) throws Exception {
         new AnonymousSubclassTest().run();
     }
 
+    ToolBox tb = new ToolBox();
+
     // To trigger the error we want, first we need to compile
     // a class with an anonymous inner class: Foo$1.
     final String foo =
@@ -65,20 +64,21 @@
         "}";
 
     void compOk(String code) throws Exception {
-        ToolBox.javac(new ToolBox.JavaToolArgs().setSources(code));
+        tb.new JavacTask()
+                .sources(code)
+                .run();
     }
 
     void compFail(String code) throws Exception {
-        ArrayList<String> errors = new ArrayList<>();
-        ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs();
-        args.setSources(code)
-            .appendArgs("-cp", ".", "-XDrawDiagnostics")
-            .set(ToolBox.Expect.FAIL)
-            .setErrOutput(errors);
-        ToolBox.javac(args);
+        String errs = tb.new JavacTask()
+                .sources(code)
+                .classpath(".")
+                .options("-XDrawDiagnostics")
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
 
-        if (!errors.get(0).contains("cant.inherit.from.anon")) {
-            System.out.println(errors.get(0));
+        if (!errs.contains("cant.inherit.from.anon")) {
             throw new Exception("test failed");
         }
     }
--- a/test/tools/javac/ClassPathTest/ClassPathTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/ClassPathTest/ClassPathTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,19 +25,14 @@
  * @test
  * @bug 4241229 4785453
  * @summary Test -classpath option and classpath defaults.
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ClassPathTest
  */
 
 import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
 
-//original test: test/tools/javac/ClassPathTest/ClassPathTest.sh
+// Original test: test/tools/javac/ClassPathTest/ClassPathTest.sh
 public class ClassPathTest {
 
     private static final String ClassPathTest1Src =
@@ -70,12 +65,12 @@
         "package pkg;\n" +
         "public class ClassPathTestAux3 {}";
 
-    ProcessBuilder pb = null;
-
     public static void main(String[] args) throws Exception {
         new ClassPathTest().test();
     }
 
+    ToolBox tb = new ToolBox();
+
     public void test() throws Exception {
         createOutputDirAndSourceFiles();
         checkCompileCommands();
@@ -83,14 +78,16 @@
 
     void createOutputDirAndSourceFiles() throws Exception {
         //dirs and files creation
-        ToolBox.createJavaFileFromSource(ClassPathTest1Src);
-        ToolBox.createJavaFileFromSource(ClassPathTest2Src);
-        ToolBox.createJavaFileFromSource(ClassPathTest3Src);
-        ToolBox.createJavaFileFromSource(Paths.get("foo"),
+        tb.writeJavaFiles(Paths.get("."),
+                ClassPathTest1Src,
+                ClassPathTest2Src,
+                ClassPathTest3Src);
+        tb.writeJavaFiles(Paths.get("foo"),
                 fooPkgClassPathTestAux1Src);
-        ToolBox.createJavaFileFromSource(Paths.get("bar"),
+        tb.writeJavaFiles(Paths.get("bar"),
                 barPkgClassPathTestAux2Src);
-        ToolBox.createJavaFileFromSource(pkgClassPathTestAux3Src);
+        tb.writeJavaFiles(Paths.get("."),
+                pkgClassPathTestAux3Src);
     }
 
     void checkCompileCommands() throws Exception {
@@ -99,80 +96,55 @@
 //        automatically but this is not happening when called using ProcessBuilder
 
 //        testJavac success ClassPathTest3.java
-        List<String> mainArgs = new ArrayList<>();
-        mainArgs.add(ToolBox.javacBinary.toString());
-        if (ToolBox.testToolVMOpts != null) {
-            mainArgs.addAll(ToolBox.testToolVMOpts);
-        }
-
-        List<String> commonArgs = new ArrayList<>();
-        commonArgs.addAll(mainArgs);
-        commonArgs.addAll(Arrays.asList("-cp", "."));
-
-        ToolBox.AnyToolArgs successParams = new ToolBox.AnyToolArgs()
-                .appendArgs(commonArgs)
-                .appendArgs("ClassPathTest3.java");
-        ToolBox.executeCommand(successParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .classpath(".")
+                .files("ClassPathTest3.java")
+                .run();
 
 //        testJavac failure ClassPathTest1.java
-        ToolBox.AnyToolArgs failParams =
-                new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(commonArgs)
-                .appendArgs("ClassPathTest1.java");
-        ToolBox.executeCommand(failParams);
-
-//        This is done inside the executeCommand method
-//        CLASSPATH=bar; export CLASSPATH
-
-        Map<String, String> extVars = new TreeMap<>();
-        extVars.put("CLASSPATH", "bar");
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .classpath(".")
+                .files("ClassPathTest1.java")
+                .run(ToolBox.Expect.FAIL);
 
 //        testJavac success ClassPathTest2.java
-        successParams = new ToolBox.AnyToolArgs()
-                .appendArgs(mainArgs)
-                .appendArgs("ClassPathTest2.java")
-                .set(extVars);
-        ToolBox.executeCommand(successParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .envVar("CLASSPATH", "bar")
+                .files("ClassPathTest2.java")
+                .run();
 
 //        testJavac failure ClassPathTest1.java
-        failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(mainArgs)
-                .appendArgs("ClassPathTest1.java")
-                .set(extVars);
-        ToolBox.executeCommand(failParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .envVar("CLASSPATH", "bar")
+                .files("ClassPathTest1.java")
+                .run(ToolBox.Expect.FAIL);
 
 //        testJavac failure ClassPathTest3.java
-        failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(mainArgs)
-                .appendArgs("ClassPathTest3.java")
-                .set(extVars);
-        ToolBox.executeCommand(failParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .envVar("CLASSPATH", "bar")
+                .files("ClassPathTest3.java")
+                .run(ToolBox.Expect.FAIL);
 
 //        testJavac success -classpath foo ClassPathTest1.java
-
-        commonArgs.clear();
-        commonArgs.addAll(mainArgs);
-        commonArgs.addAll(Arrays.asList("-cp", "foo"));
-
-        successParams = new ToolBox.AnyToolArgs()
-                .appendArgs(commonArgs)
-                .appendArgs("ClassPathTest1.java")
-                .set(extVars);
-        ToolBox.executeCommand(successParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .envVar("CLASSPATH", "bar")
+                .classpath("foo")
+                .files("ClassPathTest1.java")
+                .run();
 
 //        testJavac failure -classpath foo ClassPathTest2.java
-        failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(commonArgs)
-                .appendArgs("ClassPathTest2.java")
-                .set(extVars);
-        ToolBox.executeCommand(failParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .envVar("CLASSPATH", "bar")
+                .classpath("foo")
+                .files("ClassPathTest2.java")
+                .run(ToolBox.Expect.FAIL);
 
 //        testJavac failure -classpath foo ClassPathTest3.java
-        failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(commonArgs)
-                .appendArgs("ClassPathTest3.java")
-                .set(extVars);
-        ToolBox.executeCommand(failParams);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .envVar("CLASSPATH", "bar")
+                .classpath("foo")
+                .files("ClassPathTest3.java")
+                .run(ToolBox.Expect.FAIL);
     }
 
 }
--- a/test/tools/javac/ConstFoldTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/ConstFoldTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 8025505
  * @summary Constant folding deficiency
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ConstFoldTest
  */
@@ -45,23 +45,23 @@
             int x;
             if (1 != 2)       x=1; else x=0;
             if (1 == 2)       x=1; else x=0;
-            if ("" != null) x=1; else x=0;
-            if ("" == null) x=1; else x=0;
+            if ("" != null)   x=1; else x=0;
+            if ("" == null)   x=1; else x=0;
             if (null == null) x=1; else x=0;
             if (null != null) x=1; else x=0;
 
             x = 1 != 2        ? 1 : 0;
             x = 1 == 2        ? 1 : 0;
-            x = "" != null  ? 1 : 0;
-            x = "" == null  ? 1 : 0;
+            x = "" != null    ? 1 : 0;
+            x = "" == null    ? 1 : 0;
             x = null == null  ? 1 : 0;
             x = null != null  ? 1 : 0;
 
             boolean b;
             b = 1 != 2         && true;
             b = 1 == 2         || true;
-            b = ("" != null) && true;
-            b = ("" == null) || true;
+            b = ("" != null)   && true;
+            b = ("" == null)   || true;
             b = (null == null) && true;
             b = (null != null) || true;
         }
@@ -72,11 +72,17 @@
     final String regex = "\\sif(?:null|nonnull|eq|ne){1}\\s";
 
     void run() throws Exception {
+        ToolBox tb = new ToolBox();
+
         URL url = ConstFoldTest.class.getResource("ConstFoldTest$CFTest.class");
-        String result = ToolBox.javap(new ToolBox.JavaToolArgs().setAllArgs("-c", url.getFile()));
-        System.out.println(result);
+        List<String> result = tb.new JavapTask()
+                .options("-c")
+                .classes(url.getFile())
+                .run()
+                .write(ToolBox.OutputKind.DIRECT)
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
 
-        List<String> bad_codes = ToolBox.grep(regex, result, "\n");
+        List<String> bad_codes = tb.grep(regex, result);
         if (!bad_codes.isEmpty()) {
             for (String code : bad_codes)
                 System.out.println("Bad OpCode Found: " + code);
--- a/test/tools/javac/ExtDirs/ExtDirTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/ExtDirs/ExtDirTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,18 +25,14 @@
  * @test
  * @bug 4204897 4256097 4785453 4863609
  * @summary Test that '.jar' files in -extdirs are found.
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ExtDirTest
  */
 
 import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.List;
 
-//original test: test/tools/javac/ExtDirs/ExtDirs.sh
+// Original test: test/tools/javac/ExtDirs/ExtDirs.sh
 public class ExtDirTest {
 
     private static final String ExtDirTestClass1Src =
@@ -100,72 +96,73 @@
         "SHA-Digest: ILJOhwHg5US+yuw1Sc1d+Avu628=\n" +
         "MD5-Digest: j8wnz8wneEcuJ/gjXBBQNA==\n";
 
-    List<String> ouputDirParam = Arrays.asList("-d", ".");
-
     public static void main(String args[]) throws Exception {
         new ExtDirTest().run();
     }
 
+    private final ToolBox tb = new ToolBox();
+
     void run() throws Exception {
         createJars();
         compileWithExtDirs();
     }
 
     void createJars() throws Exception {
-        sun.tools.jar.Main jarGenerator =
-                new sun.tools.jar.Main(System.out, System.err, "jar");
+        tb.new JavacTask()
+                .outdir(".")
+                .sources(ExtDirTestClass1Src)
+                .run();
 
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs()
-                .setOptions(ouputDirParam)
-                .setSources(ExtDirTestClass1Src);
-        ToolBox.javac(javacParams);
+        tb.new JarTask("pkg1.jar")
+                .manifest(jar1Manifest)
+                .files("pkg1/ExtDirTestClass1.class")
+                .run();
 
-        ToolBox.writeFile(Paths.get("pkg1", "MANIFEST.MF"), jar1Manifest);
-        jarGenerator.run(new String[] {"cfm", "pkg1.jar", "pkg1/MANIFEST.MF",
-            "pkg1/ExtDirTestClass1.class"});
+        tb.new JavacTask()
+                .outdir(".")
+                .sources(ExtDirTestClass2Src)
+                .run();
 
-        javacParams.setSources(ExtDirTestClass2Src);
-        ToolBox.javac(javacParams);
+        tb.new JarTask("pkg2.jar")
+                .manifest(jar2Manifest)
+                .files("pkg2/ExtDirTestClass2.class")
+                .run();
 
-        ToolBox.writeFile(Paths.get("pkg2", "MANIFEST.MF"), jar2Manifest);
-        jarGenerator.run(new String[] {"cfm", "pkg2.jar", "pkg2/MANIFEST.MF",
-            "pkg2/ExtDirTestClass2.class"});
+        tb.createDirectories("ext1", "ext2", "ext3");
+        tb.copyFile("pkg1.jar", "ext1");
+        tb.copyFile("pkg2.jar", "ext2");
+        tb.copyFile("pkg1.jar", "ext3");
+        tb.copyFile("pkg2.jar", "ext3");
 
-        ToolBox.copyFile(Paths.get("ext1", "pkg1.jar"), Paths.get("pkg1.jar"));
-        ToolBox.copyFile(Paths.get("ext2", "pkg2.jar"), Paths.get("pkg2.jar"));
-        ToolBox.copyFile(Paths.get("ext3", "pkg1.jar"), Paths.get("pkg1.jar"));
-        ToolBox.copyFile(Paths.get("ext3", "pkg2.jar"), Paths.get("pkg2.jar"));
-
-        Files.delete(Paths.get("pkg1.jar"));
-        Files.delete(Paths.get("pkg2.jar"));
-
-        Files.delete(Paths.get("pkg1", "ExtDirTestClass1.class"));
-        Files.delete(Paths.get("pkg1", "MANIFEST.MF"));
-        Files.delete(Paths.get("pkg1"));
-        Files.delete(Paths.get("pkg2", "ExtDirTestClass2.class"));
-        Files.delete(Paths.get("pkg2", "MANIFEST.MF"));
-        Files.delete(Paths.get("pkg2"));
+        tb.deleteFiles(
+                "pkg1.jar",
+                "pkg2.jar",
+                "pkg1/ExtDirTestClass1.class",
+                "pkg1",
+                "pkg2/ExtDirTestClass2.class",
+                "pkg2"
+        );
     }
 
     void compileWithExtDirs() throws Exception {
+        tb.new JavacTask()
+                .outdir(".")
+                .options("-extdirs", "ext1")
+                .sources(ExtDirTest_1Src)
+                .run()
+                .writeAll();
 
-//javac -extdirs ext1 ExtDirTest_1.java
-        ToolBox.JavaToolArgs params =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-d", ".", "-extdirs", "ext1")
-                .setSources(ExtDirTest_1Src);
-        ToolBox.javac(params);
+        tb.new JavacTask()
+                .outdir(".")
+                .options("-extdirs", "ext1" + File.pathSeparator + "ext2")
+                .sources(ExtDirTest_2Src)
+                .run();
 
-//javac -extdirs ext1:ext2 ExtDirTest_2.java
-        params.setOptions("-d", ".", "-extdirs", "ext1" + File.pathSeparator + "ext2")
-                .setSources(ExtDirTest_2Src);
-        ToolBox.javac(params);
-
-//javac -extdirs ext3 ExtDirTest_3.java
-        params.setOptions("-d", ".", "-extdirs", "ext3")
-                .setSources(ExtDirTest_3Src);
-        ToolBox.javac(params);
+        tb.new JavacTask()
+                .outdir(".")
+                .options("-extdirs", "ext3")
+                .sources(ExtDirTest_3Src)
+                .run();
     }
 
 }
--- a/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 8034924
  * @summary Incorrect inheritance of inaccessible static method
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main IncorrectInheritanceTest
  */
@@ -59,10 +59,11 @@
     }
 
     public void test() throws Exception {
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs()
-                .setSources(ASrc, BSrc, CSrc);
-        ToolBox.javac(javacParams);
+        ToolBox tb = new ToolBox();
+
+        tb.new JavacTask()
+                .sources(ASrc, BSrc, CSrc)
+                .run();
     }
 
 }
--- a/test/tools/javac/MissingInclude/MissingIncludeTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/MissingInclude/MissingIncludeTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -26,25 +26,26 @@
  * @bug 4509051 4785453
  * @summary javac <AT>sourcefiles should catch Exception, when sourcefiles
  * doesn't exist.
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main MissingIncludeTest
  */
 
-//original test: test/tools/javac/MissingInclude.sh
+// Original test: test/tools/javac/MissingInclude.sh
 public class MissingIncludeTest {
 
-    private static final String MissingIncludeSrc =
-        "class MissingInclude {}";
+    private static final String MissingIncludeFile = "MissingInclude.java";
+    private static final String MissingIncludeSrc = "class MissingInclude {}";
 
     public static void main(String[] args) throws Exception {
-        ToolBox.createJavaFileFromSource(MissingIncludeSrc);
+        ToolBox tb = new ToolBox();
 
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} @/nonexistent_file MissingInclude.java 2> ${TMP1}
-        ToolBox.JavaToolArgs params =
-                new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL)
-                .setAllArgs("@/nonexistent_file", "MissingInclude.java");
-        ToolBox.javac(params);
+        tb.writeFile(MissingIncludeFile, MissingIncludeSrc);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("@/nonexistent_file")
+                .files(MissingIncludeFile)
+                .run(ToolBox.Expect.FAIL);
     }
 
 }
--- a/test/tools/javac/Paths/AbsolutePathTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/Paths/AbsolutePathTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -26,33 +26,45 @@
  * @bug 8030046
  * @summary javac incorrectly handles absolute paths in manifest classpath
  * @author govereau
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main AbsolutePathTest
  */
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
 public class AbsolutePathTest {
     public static void main(String... cmdline) throws Exception {
+        ToolBox tb = new ToolBox();
+
         // compile test.Test
-        ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs();
-        args.appendArgs("-d", "."); // this is needed to get the classfiles in test
-        ToolBox.javac(args.setSources("package test; public class Test{}"));
+        tb.new JavacTask()
+                .outdir(".") // this is needed to get the classfiles in test
+                .sources("package test; public class Test{}")
+                .run();
 
         // build test.jar containing test.Test
         // we need the jars in a directory different from the working
-        // directory to trigger the bug. I will reuse test/
-        ToolBox.jar("cf", "test/test.jar", "test/Test.class");
+        // directory to trigger the bug.
+        Files.createDirectory(Paths.get("jars"));
+        tb.new JarTask("jars/test.jar")
+                .files("test/Test.class")
+                .run();
 
-        // build second jar in test directory using
+        // build second jar in jars directory using
         // an absolute path reference to the first jar
-        String path = new File("test/test.jar").getAbsolutePath();
-        ToolBox.mkManifestWithClassPath(null, path);
-        ToolBox.jar("cfm", "test/test2.jar", "MANIFEST.MF");
+        tb.new JarTask("jars/test2.jar")
+                .classpath(new File("jars/test.jar").getAbsolutePath())
+                .run();
 
         // this should not fail
-        args.appendArgs("-cp", ".");
-        ToolBox.javac(args.setSources("import test.Test; class Test2 {}"));
+        tb.new JavacTask()
+                .outdir(".")
+                .classpath("jars/test2.jar")
+                .sources("import test.Test; class Test2 {}")
+                .run()
+                .writeAll();
     }
 }
--- a/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,13 +25,13 @@
  * @test
  * @bug 4087314 4800342 4307565
  * @summary Verify allowed access to protected class from another package
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ProtectedInnerClassesTest
  */
 
-//original tests: test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh
-//and test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java
+// Original tests: test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh
+// and test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java
 public class ProtectedInnerClassesTest {
 
     private static final String protectedInnerClass1Src =
@@ -74,45 +74,36 @@
         new ProtectedInnerClassesTest().run();
     }
 
+    ToolBox tb = new ToolBox();
+
     void run() throws Exception {
         compileAndExecute();
         compileOnly();
     }
 
     void compileAndExecute() throws Exception {
-//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d "${TESTCLASSES}" "${TESTSRC}${FS}p1${FS}ProtectedInnerClass1.java" "${TESTSRC}${FS}p2${FS}ProtectedInnerClass2.java"
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-d", ".")
-                .setSources(protectedInnerClass1Src, protectedInnerClass2Src);
+        tb.new JavacTask()
+                .outdir(".")
+                .sources(protectedInnerClass1Src, protectedInnerClass2Src)
+                .run();
 
-        ToolBox.javac(javacParams);
-
-//"${TESTJAVA}${FS}bin${FS}java" ${TESTVMOPTS} -classpath "${CLASSPATH}${PS}${TESTCLASSES}" p2.ProtectedInnerClass2
-        ToolBox.AnyToolArgs javaParams =
-                new ToolBox.AnyToolArgs()
-                .appendArgs(ToolBox.javaBinary)
-                .appendArgs(ToolBox.testVMOpts)
-                .appendArgs("-classpath", System.getProperty("user.dir"),
-                    "p2.ProtectedInnerClass2");
-        ToolBox.executeCommand(javaParams);
+        tb.new JavaTask()
+                .classpath(System.getProperty("user.dir"))
+                .className("p2.ProtectedInnerClass2")
+                .run();
     }
 
 //from test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java
     void compileOnly() throws Exception {
-//@run compile p1/ProtectedInnerClass1.java
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs()
-                .appendArgs("-d", ".")
-                .setSources(protectedInnerClass1Src);
+        tb.new JavacTask()
+                .outdir(".")
+                .sources(protectedInnerClass1Src)
+                .run();
 
-        ToolBox.javac(javacParams);
-
-//@run compile/fail p2/ProtectedInnerClass3.java
-        javacParams = new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs("-d", ".")
-                .setSources(protectedInnerClass3Src);
-        ToolBox.javac(javacParams);
+        tb.new JavacTask()
+                .outdir(".")
+                .sources(protectedInnerClass3Src)
+                .run(ToolBox.Expect.FAIL);
     }
 
 }
--- a/test/tools/javac/T5090006/AssertionFailureTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T5090006/AssertionFailureTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 5090006
  * @summary javac fails with assertion error
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main AssertionFailureTest
  */
@@ -33,7 +33,7 @@
 import java.io.File;
 import java.nio.file.Paths;
 
-//original test: test/tools/javac/T5090006/compiler.sh
+// Original test: test/tools/javac/T5090006/compiler.sh
 public class AssertionFailureTest {
 
     private static final String testSrc =
@@ -54,16 +54,14 @@
         "}";
 
     public static void main(String args[]) throws Exception {
-        String classpath = Paths.get(System.getProperty("test.src"), "broken.jar")
-                .toString();
-        classpath = new StringBuilder(classpath)
-                .append(File.pathSeparator).append(".").toString();
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -verbose -d "${TESTCLASSES}" -cp "${TESTSRC}${FS}broken.jar" "${TESTSRC}${FS}$1"
-        ToolBox.JavaToolArgs params =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-cp", classpath)
-                .setSources(testSrc);
-        ToolBox.javac(params);
+        ToolBox tb = new ToolBox();
+        String classpath = Paths.get(tb.testSrc, "broken.jar")
+                + File.pathSeparator
+                + ".";
+        tb.new JavacTask()
+                .classpath(classpath)
+                .sources(testSrc)
+                .run();
     }
 
 }
--- a/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 6970173
  * @summary Debug pointer at bad position
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main DebugPointerAtBadPositionTest
  */
@@ -75,9 +75,10 @@
     }
 
     void compileTestClass() throws Exception {
-        ToolBox.JavaToolArgs javacSuccessArgs =
-                new ToolBox.JavaToolArgs().setSources(testSource);
-        ToolBox.javac(javacSuccessArgs);
+        ToolBox tb = new ToolBox();
+        tb.new JavacTask()
+                .sources(testSource)
+                .run();
     }
 
     void checkClassFile(final File cfile, String methodToFind) throws Exception {
--- a/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 7008643
  * @summary inlined finally clauses confuse debuggers
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main InlinedFinallyConfuseDebuggersTest
  */
@@ -73,6 +73,8 @@
         new InlinedFinallyConfuseDebuggersTest().run();
     }
 
+    ToolBox tb = new ToolBox();
+
     void run() throws Exception {
         compileTestClass();
         checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
@@ -80,9 +82,9 @@
     }
 
     void compileTestClass() throws Exception {
-        ToolBox.JavaToolArgs javacSuccessArgs =
-                new ToolBox.JavaToolArgs().setSources(testSource);
-        ToolBox.javac(javacSuccessArgs);
+        tb.new JavacTask()
+                .sources(testSource)
+                .run();
     }
 
     void checkClassFile(final File cfile, String methodToFind) throws Exception {
--- a/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,14 +27,13 @@
  * @test
  * @bug 8009640
  * @summary -profile <compact> does not work when -bootclasspath specified
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main CheckRejectProfileBCPOptionsIfUsedTogetherTest
  */
 
 import com.sun.tools.javac.util.Assert;
-import java.util.ArrayList;
-import java.util.List;
+import java.nio.file.Paths;
 
 public class CheckRejectProfileBCPOptionsIfUsedTogetherTest {
 
@@ -44,21 +43,16 @@
         "}";
 
     public static void main(String args[]) throws Exception {
-        List<String> errOutput = new ArrayList<>();
-        String testJDK = ToolBox.jdkUnderTest;
-        ToolBox.createJavaFileFromSource(TestSrc);
+        ToolBox tb = new ToolBox();
 
-        ToolBox.AnyToolArgs javacParams =
-                new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(ToolBox.javacBinary)
-                .appendArgs(ToolBox.testToolVMOpts)
-                .appendArgs("-profile", "compact1", "-bootclasspath",
-                testJDK + "/jre/lib/rt.jar", "Test.java")
-                .setErrOutput(errOutput);
+        ToolBox.Result result = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-profile", "compact1",
+                        "-bootclasspath", Paths.get(ToolBox.testJDK, "jre/lib/rt.jar").toString())
+                .sources(TestSrc)
+                .run(ToolBox.Expect.FAIL);
 
-        ToolBox.executeCommand(javacParams);
-
-        Assert.check(errOutput.get(0).startsWith(
+        String out = result.getOutput(ToolBox.OutputKind.DIRECT);
+        Assert.check(out.startsWith(
                 "javac: profile and bootclasspath options cannot be used together"),
                 "Incorrect javac error output");
     }
--- a/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,7 +27,7 @@
  * @test
  * @bug 8010659
  * @summary Javac Crashes while building OpenJFX
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main CompilerCrashWhenMixingBinariesAndSourcesTest
  */
@@ -48,19 +48,18 @@
             "        Object m(int i) {return null;}\n" +
             "}";
 
-    public static void main (String[] args) throws Exception{
-        ToolBox.JavaToolArgs javacParams = new ToolBox.JavaToolArgs()
-                .setSources(ASource, BSource, CSource, DSource);
-        ToolBox.javac(javacParams);
+    public static void main(String[] args) throws Exception {
+        ToolBox tb = new ToolBox();
 
-        ToolBox.rm("A.class");
-        ToolBox.rm("A$1.class");
-        ToolBox.rm("C.class");
-        ToolBox.rm("D.class");
+        tb.new JavacTask()
+                .sources(ASource, BSource, CSource, DSource)
+                .run();
 
-        javacParams = new ToolBox.JavaToolArgs()
-                .setOptions("-cp", ".")
-                .setSources(ASource, CSource, DSource);
-        ToolBox.javac(javacParams);
+        tb.deleteFiles("A.class", "A$1.class", "C.class", "D.class");
+
+        tb.new JavacTask()
+                .classpath(".")
+                .sources(ASource, CSource, DSource)
+                .run();
     }
 }
--- a/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,7 +27,7 @@
  * @test
  * @bug 8013394
  * @summary compile of iterator use fails with error "defined in an inaccessible class or interface"
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main CompileErrorWithIteratorTest
  */
@@ -71,15 +71,16 @@
         new CompileErrorWithIteratorTest().run();
     }
 
+    ToolBox tb = new ToolBox();
+
     void run() throws Exception {
         compile();
     }
 
     void compile() throws Exception {
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs()
-                .setSources(TestCollectionSrc, TestSrc);
-        ToolBox.javac(javacParams);
+        tb.new JavacTask()
+                .sources(TestCollectionSrc, TestSrc)
+                .run();
     }
 
 }
--- a/test/tools/javac/T8019486/WrongLNTForLambdaTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8019486/WrongLNTForLambdaTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,7 +27,7 @@
  * @test
  * @bug 8019486 8026861 8027142
  * @summary javac, generates erroneous LVT for a test case with lambda code
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main WrongLNTForLambdaTest
  */
@@ -125,6 +125,8 @@
         new WrongLNTForLambdaTest().run();
     }
 
+    ToolBox tb = new ToolBox();
+
     void run() throws Exception {
         compileTestClass();
         checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
@@ -146,9 +148,9 @@
     }
 
     void compileTestClass() throws Exception {
-        ToolBox.JavaToolArgs javacSuccessArgs =
-                new ToolBox.JavaToolArgs().setSources(testSource);
-        ToolBox.javac(javacSuccessArgs);
+        tb.new JavacTask()
+                .sources(testSource)
+                .run();
     }
 
     void checkClassFile(final File cfile, String methodToFind, int[][] expectedLNT) throws Exception {
--- a/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,14 +25,11 @@
  * @test
  * @bug 8022162
  * @summary Incorrect signature determination for certain inner class generics
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main IncorrectSignatureDeterminationForInnerClassesTest
  */
 
-import java.nio.file.Files;
-import java.nio.file.Paths;
-
 public class IncorrectSignatureDeterminationForInnerClassesTest {
 
     private static final String DSrc =
@@ -69,21 +66,20 @@
     }
 
     void compile() throws Exception {
-        Files.createDirectory(Paths.get("classes"));
+        ToolBox tb = new ToolBox();
+        tb.createDirectories("classes");
 
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs()
-                .appendArgs("-d", "classes")
-                .setSources(DSrc);
-
-        ToolBox.javac(javacParams);
+        tb.new JavacTask()
+                .outdir("classes")
+                .sources(DSrc)
+                .run();
 
         // compile class H against the class files for classes D and Q
-        javacParams =
-                new ToolBox.JavaToolArgs()
-                .appendArgs("-d", "classes", "-cp", "classes")
-                .setSources(HSrc);
-        ToolBox.javac(javacParams);
+        tb.new JavacTask()
+                .outdir("classes")
+                .classpath("classes")
+                .sources(HSrc)
+                .run();
     }
 
 }
--- a/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,7 +27,7 @@
  * @test
  * @bug 8024039
  * @summary javac, previous solution for JDK-8022186 was incorrect
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main NoDeadCodeGenerationOnTrySmtTest
  */
@@ -76,6 +76,8 @@
 
     static final String[] methodsToLookFor = {"m1", "m2"};
 
+    ToolBox tb = new ToolBox();
+
     public static void main(String[] args) throws Exception {
         new NoDeadCodeGenerationOnTrySmtTest().run();
     }
@@ -87,9 +89,9 @@
     }
 
     void compileTestClass() throws Exception {
-        ToolBox.JavaToolArgs javacSuccessArgs =
-                new ToolBox.JavaToolArgs().setSources(testSource);
-        ToolBox.javac(javacSuccessArgs);
+        tb.new JavacTask()
+                .sources(testSource)
+                .run();
     }
 
     void checkClassFile(final File cfile, String[] methodsToFind) throws Exception {
--- a/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,7 +27,7 @@
  * @test
  * @bug 8024437
  * @summary Inferring the exception thrown by a lambda: sometimes fails to compile
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ExceptionInferenceFromClassFileTest
  */
@@ -56,19 +56,19 @@
             "}";
 
     public static void main(String[] args) throws Exception {
-        Files.createDirectory(Paths.get("out"));
+        ToolBox tb = new ToolBox();
+        tb.createDirectories("out");
 
-        ToolBox.JavaToolArgs compileABParams =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-d", "out")
-                .setSources(ABSrc);
-        ToolBox.javac(compileABParams);
+        tb.new JavacTask()
+                .outdir("out")
+                .sources(ABSrc)
+                .run();
 
-        ToolBox.JavaToolArgs compileCParams =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-d", "out", "-cp", "out")
-                .setSources(CSrc);
-        ToolBox.javac(compileCParams);
+        tb.new JavacTask()
+                .outdir("out")
+                .classpath("out")
+                .sources(CSrc)
+                .run();
     }
 
 }
--- a/test/tools/javac/api/ToolProvider/HelloWorldTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/api/ToolProvider/HelloWorldTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, 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
@@ -25,21 +25,19 @@
  * @test
  * @bug 6604599
  * @summary ToolProvider should be less compiler-specific
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main HelloWorldTest
  */
 
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 
 // verify that running a simple program, such as this one, does not trigger
 // the loading of ToolProvider or any com.sun.tools.javac class
 public class HelloWorldTest {
     public static void main(String... args) throws Exception {
         if (args.length > 0) {
-            System.err.println(Arrays.asList(args));
+            System.err.println(Arrays.toString(args));
             return;
         }
 
@@ -47,27 +45,26 @@
     }
 
     void run() throws Exception {
+        ToolBox tb = new ToolBox();
+
         String classpath = System.getProperty("java.class.path");
 
-        List<String> output = new ArrayList<>();
-        ToolBox.AnyToolArgs javaParams =
-                new ToolBox.AnyToolArgs()
-                        .appendArgs(ToolBox.javaBinary)
-                        .appendArgs(ToolBox.testVMOpts)
-                        .appendArgs(ToolBox.testJavaOpts)
-                        .appendArgs("-verbose:class",
-                                "-classpath", classpath,
-                                HelloWorldTest.class.getName(),
-                                "Hello", "World")
-                        .setErrOutput(output)
-                        .setStdOutput(output);
+        ToolBox.Result tr = tb.new JavaTask()
+                .vmOptions("-verbose:class")
+                .classpath(classpath)
+                .className(HelloWorldTest.class.getName())
+                .classArgs("Hello", "World")
+                .run();
 
-       ToolBox.executeCommand(javaParams);
-
-        for (String line : output) {
-            System.err.println(line);
-            if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac."))
-                error(">>> " + line);
+        if (tr.getOutput(ToolBox.OutputKind.STDOUT).contains("java.lang.Object")) {
+            for (String line : tr.getOutputLines(ToolBox.OutputKind.STDOUT)) {
+                System.err.println(line);
+                if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac."))
+                    error(">>> " + line);
+            }
+        } else {
+            tr.writeAll();
+            error("verbose output not as expected");
         }
 
         if (errors > 0)
--- a/test/tools/javac/api/ToolProvider/ToolProviderTest1.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/api/ToolProvider/ToolProviderTest1.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, 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
@@ -25,12 +25,11 @@
  * @test
  * @bug 6604599
  * @summary ToolProvider should be less compiler-specific
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ToolProviderTest1
  */
 
-import java.util.ArrayList;
 import java.util.List;
 
 // verify that running accessing ToolProvider by itself does not
@@ -46,24 +45,18 @@
     }
 
     void run() throws Exception {
+        ToolBox tb = new ToolBox();
         String classpath = System.getProperty("java.class.path");
 
-        List<String> output = new ArrayList<>();
-        ToolBox.AnyToolArgs javaParams =
-                new ToolBox.AnyToolArgs()
-                        .appendArgs(ToolBox.javaBinary)
-                        .appendArgs(ToolBox.testVMOpts)
-                        .appendArgs(ToolBox.testJavaOpts)
-                        .appendArgs("-verbose:class",
-                                "-classpath", classpath,
-                                ToolProviderTest1.class.getName(),
-                                "javax.tools.ToolProvider")
-                        .setErrOutput(output)
-                        .setStdOutput(output);
+        List<String> lines = tb.new JavaTask()
+                .vmOptions("-verbose:class")
+                .classpath(classpath)
+                .className(getClass().getName())
+                .classArgs("javax.tools.ToolProvider")
+                .run()
+                .getOutputLines(ToolBox.OutputKind.STDOUT);
 
-        ToolBox.executeCommand(javaParams);
-
-        for (String line : output) {
+        for (String line : lines) {
             System.err.println(line);
             if (line.contains("com.sun.tools.javac."))
                 error(">>> " + line);
--- a/test/tools/javac/api/ToolProvider/ToolProviderTest2.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/api/ToolProvider/ToolProviderTest2.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, 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
@@ -25,13 +25,12 @@
  * @test
  * @bug 6604599
  * @summary ToolProvider should be less compiler-specific
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ToolProviderTest2
  */
 
 import javax.tools.ToolProvider;
-import java.util.ArrayList;
 import java.util.List;
 
 // control for ToolProviderTest1 -- verify that using ToolProvider to
@@ -47,25 +46,19 @@
     }
 
     void run() throws Exception {
+        ToolBox tb = new ToolBox();
         String classpath = System.getProperty("java.class.path");
 
-        List<String> output = new ArrayList<>();
-        ToolBox.AnyToolArgs javaParams =
-                new ToolBox.AnyToolArgs()
-                        .appendArgs(ToolBox.javaBinary)
-                        .appendArgs(ToolBox.testVMOpts)
-                        .appendArgs(ToolBox.testJavaOpts)
-                        .appendArgs( "-verbose:class",
-                                "-classpath", classpath,
-                                ToolProviderTest2.class.getName(),
-                                "javax.tools.ToolProvider")
-                        .setErrOutput(output)
-                        .setStdOutput(output);
-
-        ToolBox.executeCommand(javaParams);
+        List<String> lines = tb.new JavaTask()
+                .vmOptions("-verbose:class")
+                .classpath(classpath)
+                .className(getClass().getName())
+                .classArgs("javax.tools.ToolProvider")
+                .run()
+                .getOutputLines(ToolBox.OutputKind.STDOUT);
 
         boolean found = false;
-        for (String line : output) {
+        for (String line : lines) {
             System.err.println(line);
             if (line.contains("com.sun.tools.javac."))
                 found = true;
--- a/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary local variable table attribute test.
  * @bug 8040097
- * @library /tools/javac/lib ../lib
- * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager
  * @compile -g LocalVariableTableTest.java
  * @run main LocalVariableTableTest
  */
--- a/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary local variable type table attribute test.
  * @bug 8040097
- * @library /tools/javac/lib ../lib
- * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager
  * @compile -g LocalVariableTypeTableTest.java
  * @run main LocalVariableTypeTableTest
  */
--- a/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for anonymous class.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main AnonymousClassTest
  */
 
--- a/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for inner class.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main InnerClassTest
  */
 
--- a/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for local class.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main LocalClassTest
  */
 
--- a/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for complex structure of nested classes and other types.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main MixTest
  */
 
--- a/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for file compiled without debug information.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @compile -g:none NoSourceFileAttribute.java
  * @run main NoSourceFileAttribute
  */
--- a/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for synthetic class.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main SyntheticClassTest
  */
 
--- a/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @summary sourcefile attribute test for two type in one file.
  * @bug 8040129
- * @library /tools/javac/lib ../lib
- * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main TopLevelClassesOneFileTest
  */
 
--- a/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -25,8 +25,8 @@
  * @test
  * @bug 8042261
  * @summary Checking that deprecated attribute does not apply to classes of deprecated package.
- * @library /tools/javac/lib ../lib
- * @build DeprecatedPackageTest TestBase TestResult InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build  ToolBox TestBase TestResult InMemoryFileManager
  * @run main DeprecatedPackageTest
  */
 
--- a/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -26,8 +26,8 @@
  * @bug 8042261
  * @summary Checking what attribute is generated by annotation Deprecated
  *          or javadoc deprecated for field, method, class(inner/local), interface.
- * @library /tools/javac/lib ../lib
- * @build DeprecatedTest TestBase TestResult InMemoryFileManager ToolBox
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build ToolBox TestBase TestResult InMemoryFileManager
  * @run main DeprecatedTest
  */
 
--- a/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java	Wed Aug 13 13:20:31 2014 -0700
@@ -26,7 +26,7 @@
  * @bug 8029240 8030855
  * @summary Default methods not always visible under -source 7
  * Default methods should be visible under source previous to 8
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main DefaultMethodsNotVisibleForSourceLessThan8Test
  */
@@ -111,6 +111,7 @@
 
     String outDir;
     String source;
+    ToolBox tb = new ToolBox();
 
     void run(String source) throws Exception {
         this.source = source;
@@ -127,50 +128,53 @@
         /* as an extra check let's make sure that interface 'I' can't be compiled
          * with source < 8
          */
-        ToolBox.JavaToolArgs javacArgs =
-                new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL)
-                .setOptions("-d", outDir, "-source", source)
-                .setSources(ISrc);
-        ToolBox.javac(javacArgs);
+        tb.new JavacTask()
+                .outdir(outDir)
+                .options("-source", source)
+                .sources(ISrc)
+                .run(ToolBox.Expect.FAIL);
 
         //but it should compile with source >= 8
-        javacArgs =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-d", outDir)
-                .setSources(ISrc);
-        ToolBox.javac(javacArgs);
+        tb.new JavacTask()
+                .outdir(outDir)
+                .sources(ISrc)
+                .run();
 
-        javacArgs =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-cp", outDir, "-d", outDir, "-source", source)
-                .setSources(JSrc, ASrc, BSrc);
-        ToolBox.javac(javacArgs);
+        tb.new JavacTask()
+                .outdir(outDir)
+                .classpath(outDir)
+                .options("-source", source)
+                .sources(JSrc, ASrc, BSrc)
+                .run();
     }
 
     void testLegacyImplementations() throws Exception {
         //compile C1-4
-        ToolBox.JavaToolArgs javacArgs =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-cp", outDir, "-d", outDir, "-source", source)
-                .setSources(C1Src, C2Src, C3Src, C4Src);
-        ToolBox.javac(javacArgs);
+        tb.new JavacTask()
+                .outdir(outDir)
+                .classpath(outDir)
+                .options("-source", source)
+                .sources(C1Src, C2Src, C3Src, C4Src)
+                .run();
     }
 
     void testLegacyInvocations() throws Exception {
         //compile LegacyInvocation
-        ToolBox.JavaToolArgs javacArgs =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-cp", outDir, "-d", outDir, "-source", source)
-                .setSources(LegacyInvocationSrc);
-        ToolBox.javac(javacArgs);
+        tb.new JavacTask()
+                .outdir(outDir)
+                .classpath(outDir)
+                .options("-source", source)
+                .sources(LegacyInvocationSrc)
+                .run();
     }
 
     void testSuperInvocations() throws Exception {
         //compile SubA, SubB
-        ToolBox.JavaToolArgs javacArgs =
-                new ToolBox.JavaToolArgs()
-                .setOptions("-cp", outDir, "-d", outDir, "-source", source)
-                .setSources(SubASrc, SubBSrc);
-        ToolBox.javac(javacArgs);
+        tb.new JavacTask()
+                .outdir(outDir)
+                .classpath(outDir)
+                .options("-source", source)
+                .sources(SubASrc, SubBSrc)
+                .run();
     }
 }
--- a/test/tools/javac/fatalErrors/NoJavaLangTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/fatalErrors/NoJavaLangTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,15 +25,12 @@
  * @test
  * @bug 4263768 4785453
  * @summary Verify that the compiler does not crash when java.lang is not
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main NoJavaLangTest
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
-//original test: test/tools/javac/fatalErrors/NoJavaLang.sh
+// Original test: test/tools/javac/fatalErrors/NoJavaLang.sh
 public class NoJavaLangTest {
 
     private static final String noJavaLangSrc =
@@ -49,26 +46,20 @@
         "Fatal Error: Unable to find package java.lang in classpath or bootclasspath";
 
     public static void main(String[] args) throws Exception {
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} NoJavaLang.java 2> "${TMP1}"
-        ToolBox.JavaToolArgs javacSuccessArgs =
-                new ToolBox.JavaToolArgs().setSources(noJavaLangSrc);
-        ToolBox.javac(javacSuccessArgs);
+        ToolBox tb = new ToolBox();
 
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -bootclasspath . NoJavaLang.java 2> "${TMP1}"
-        List<String> output = new ArrayList<>();
-        ToolBox.JavaToolArgs javacFailArgs =
-                new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL)
-                .setOptions("-bootclasspath", ".")
-                .setSources(noJavaLangSrc)
-                .setErrOutput(output);
+        tb.new JavacTask()
+                .sources(noJavaLangSrc)
+                .run();
 
-        int cr = ToolBox.javac(javacFailArgs);
-        if (cr != 3) {
-            throw new AssertionError("Compiler exit result should be 3");
-        }
+        String out = tb.new JavacTask()
+                .options("-bootclasspath", ".")
+                .sources(noJavaLangSrc)
+                .run(ToolBox.Expect.FAIL, 3)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
 
-//        diff ${DIFFOPTS} -c "${TESTSRC}${FS}NoJavaLang.out" "${TMP1}"
-        if (!(output.size() == 1 && output.get(0).equals(compilerErrorMessage))) {
+        if (!out.trim().equals(compilerErrorMessage)) {
             throw new AssertionError("javac generated error output is not correct");
         }
     }
--- a/test/tools/javac/innerClassFile/InnerClassFileTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/innerClassFile/InnerClassFileTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,14 +25,15 @@
  * @test
  * @bug 4491755 4785453
  * @summary Prob w/static inner class with same name as a regular class
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main InnerClassFileTest
  */
 
+import java.nio.file.Path;
 import java.nio.file.Paths;
 
-//original test: test/tools/javac/innerClassFile/Driver.sh
+// Original test: test/tools/javac/innerClassFile/Driver.sh
 public class InnerClassFileTest {
 
     private static final String BSrc =
@@ -90,38 +91,37 @@
         new InnerClassFileTest().run();
     }
 
+    private final ToolBox tb = new ToolBox();
+
     void run() throws Exception {
         createFiles();
         compileFiles();
     }
 
     void createFiles() throws Exception {
-//        mkdir src
-//        cp -r ${TESTSRC}${FS}* src
-        ToolBox.createJavaFileFromSource(Paths.get("src"), BSrc);
-        ToolBox.createJavaFileFromSource(Paths.get("src"), CSrc);
-        ToolBox.createJavaFileFromSource(Paths.get("src"), MainSrc);
-        ToolBox.createJavaFileFromSource(Paths.get("src"), R1Src);
-        ToolBox.createJavaFileFromSource(Paths.get("src"), R2Src);
-        ToolBox.createJavaFileFromSource(Paths.get("src"), R3Src);
+        Path srcDir = Paths.get("src");
+        tb.writeJavaFiles(srcDir, BSrc, CSrc, MainSrc, R1Src, R2Src, R3Src);
     }
 
     void compileFiles() throws Exception {
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . -classpath .
-//              -sourcepath src src/x/B.java src/x/C.java src/y/Main.java
-        ToolBox.JavaToolArgs args =
-                new ToolBox.JavaToolArgs()
-                .setAllArgs("-d", ".", "-cp" , ".", "-sourcepath", "src",
-                "src/x/B.java", "src/x/C.java", "src/y/Main.java");
-        ToolBox.javac(args);
+        tb.new JavacTask()
+                .outdir(".")
+                .classpath(".")
+                .sourcepath("src")
+                .files("src/x/B.java", "src/x/C.java", "src/y/Main.java")
+                .run()
+                .writeAll();
 
-//        rm y/R3.class
-        ToolBox.rm(Paths.get("y", "R3.class"));
+        tb.deleteFiles("y/R3.class");
 
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . -classpath .
-//                -sourcepath src src/y/Main.java
-        args.setAllArgs("-d", ".", "-cp", ".", "-sourcepath", "src", "src/y/Main.java");
-        ToolBox.javac(args);
+        tb.new JavacTask()
+                .outdir(".")
+                .classpath(".")
+                .sourcepath("src")
+                .files("src/y/Main.java")
+                .run()
+                .writeAll();
+
     }
 
 }
--- a/test/tools/javac/javazip/JavaZipTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/javazip/JavaZipTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,15 +25,16 @@
  * @test
  * @bug 4098712 6304984 6388453
  * @summary check that source files inside zip files on the class path are ignored
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main JavaZipTest
  */
 
-import java.io.File;
+import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.util.Arrays;
 
-//original test: test/tools/javac/javazip/Test.sh
+// Original test: test/tools/javac/javazip/Test.sh
 public class JavaZipTest {
 
     private static final String ASrc =
@@ -62,7 +63,7 @@
         {"-d", "output", "-cp", "good.jar", "A.java"},
     };
 
-    private static final String[][] unSuccessfulCompilationArgs = {
+    private static final String[][] unsuccessfulCompilationArgs = {
         {"-d", "output", "A.java", "bad/B.java"},
         {"-d", "output", "-cp", "bad", "A.java"},
         {"-d", "output", "-sourcepath", "bad", "A.java"},
@@ -74,53 +75,57 @@
         new JavaZipTest().test();
     }
 
+    private final ToolBox tb = new ToolBox();
+
     public void test() throws Exception {
         createOutputDirAndSourceFiles();
         createZipsAndJars();
         check(ToolBox.Expect.SUCCESS, successfulCompilationArgs);
-        check(ToolBox.Expect.FAIL, unSuccessfulCompilationArgs);
+        check(ToolBox.Expect.FAIL, unsuccessfulCompilationArgs);
     }
 
     void createOutputDirAndSourceFiles() throws Exception {
         //create output dir
-        new File("output").mkdir();
+        Files.createDirectory(Paths.get("output"));
 
         //source file creation
-        ToolBox.createJavaFileFromSource(Paths.get("good"), BGoodSrc);
-        ToolBox.createJavaFileFromSource(Paths.get("bad"), BBadSrc);
-        ToolBox.createJavaFileFromSource(ASrc);
+        tb.writeJavaFiles(Paths.get("good"), BGoodSrc);
+        tb.writeJavaFiles(Paths.get("bad"), BBadSrc);
+        tb.writeJavaFiles(ToolBox.currDir, ASrc);
     }
 
     void createZipsAndJars() throws Exception {
         //jar and zip creation
-//        check ok   "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}good.jar" -C "${TESTSRC}${FS}good" B.java
-//        check ok   "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}good.zip" -C "${TESTSRC}${FS}good" B.java
-//        check ok   "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}bad.jar"  -C "${TESTSRC}${FS}bad" B.java
-//        check ok   "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}bad.zip"  -C "${TESTSRC}${FS}bad" B.java
         for (String[] args: jarArgs) {
-            ToolBox.jar(args);
+            tb.new JarTask().run(args).writeAll();
         }
     }
 
-    void check(ToolBox.Expect whatToExpect, String[][] theArgs) throws Exception {
-//        check ok   "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} "${TESTSRC}${FS}A.java" "${TESTSRC}${FS}good${FS}B.java"
-//        check ok   "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${TESTSRC}${FS}good"   "${TESTSRC}${FS}A.java"
-//        check ok   "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${TESTSRC}${FS}good"  "${TESTSRC}${FS}A.java"
-//        check ok   "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${SCR}${FS}good.zip"   "${TESTSRC}${FS}A.java"
-//        check ok   "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${SCR}${FS}good.jar"   "${TESTSRC}${FS}A.java"
+    void check(ToolBox.Expect expectedStatus, String[][] theArgs) throws Exception {
 
-//        check err  "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} "${TESTSRC}${FS}A.java" "${TESTSRC}${FS}bad${FS}B.java"
-//        check err  "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${TESTSRC}${FS}bad"    "${TESTSRC}${FS}A.java"
-//        check err  "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${TESTSRC}${FS}bad"   "${TESTSRC}${FS}A.java"
-//        check err  "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${SCR}${FS}bad.zip"   "${TESTSRC}${FS}A.java"
-//        check err  "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${SCR}${FS}bad.jar"   "${TESTSRC}${FS}A.java"
-        ToolBox.JavaToolArgs args =
-                new ToolBox.JavaToolArgs(whatToExpect);
 
         for (String[] allArgs: theArgs) {
-            args.setAllArgs(allArgs);
-            ToolBox.javac(args);
+            tb.new JavacTask()
+                    .options(opts(allArgs))
+                    .files(files(allArgs))
+                    .run(expectedStatus)
+                    .writeAll();
+
         }
     }
 
+    private String[] opts(String... allArgs) {
+        int i = allArgs.length;
+        while (allArgs[i - 1].endsWith(".java"))
+            i--;
+        return Arrays.copyOfRange(allArgs, 0, i);
+    }
+
+    private String[] files(String... allArgs) {
+        int i = allArgs.length;
+        while (allArgs[i - 1].endsWith(".java"))
+            i--;
+        return Arrays.copyOfRange(allArgs, i, allArgs.length);
+    }
+
 }
--- a/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8023668
  * @summary Desugar serializable lambda bodies using more robust naming scheme
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main TestSerializedLambdaNameStability
  */
@@ -125,6 +125,7 @@
         static final String compiledDir = System.getProperty("user.dir");
         static final String sourceBaseDir = System.getProperty("test.src");
 
+        final ToolBox tb = new ToolBox();
         final String context;
 
         public TestClassLoader(String context) {
@@ -154,10 +155,10 @@
             else
                 throw new Exception("Did not expect to load " + name);
             Path srcFile = Paths.get(sourceBaseDir, context, srcName + ".java");
-            String testSource = new String(Files.readAllBytes(srcFile));
-            ToolBox.JavaToolArgs javacSuccessArgs =
-                    new ToolBox.JavaToolArgs().setSources(testSource);
-            ToolBox.javac(javacSuccessArgs);
+            tb.new JavacTask()
+                    .outdir(compiledDir)
+                    .files(srcFile)
+                    .run();
             Path cfFile = Paths.get(compiledDir, name + ".class");
             byte[] bytes = Files.readAllBytes(cfFile);
             return bytes;
--- a/test/tools/javac/lib/ToolBox.java	Wed Aug 13 14:25:46 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1080 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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 java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.tools.FileObject;
-import javax.tools.ForwardingJavaFileManager;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import javax.tools.JavaFileObject.Kind;
-import javax.tools.SimpleJavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-import com.sun.source.util.JavacTask;
-import com.sun.tools.javac.api.JavacTaskImpl;
-
-import sun.tools.jar.Main;
-
-import static java.nio.file.StandardCopyOption.*;
-
-/**
- * Toolbox for jtreg tests.
- */
-
-public class ToolBox {
-
-    public static final String lineSeparator = System.getProperty("line.separator");
-    public static final String jdkUnderTest = System.getProperty("test.jdk");
-    public static final Path javaBinary = Paths.get(jdkUnderTest, "bin", "java");
-    public static final Path javacBinary = Paths.get(jdkUnderTest, "bin", "javac");
-
-    public static final List<String> testVMOpts = readOptions("test.vm.opts");
-    public static final List<String> testToolVMOpts = readOptions("test.tool.vm.opts");
-    public static final List<String> testJavaOpts = readOptions("test.java.opts");
-
-    private static final Charset defaultCharset = Charset.defaultCharset();
-
-    static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
-
-    private static List<String> readOptions(String property) {
-        String options = System.getProperty(property, "");
-        return options.length() > 0 ? Arrays.asList(options.split("\\s+")) : Collections.<String>emptyList();
-    }
-
-    /**
-     * The expected result of command-like method execution.
-     */
-    public enum Expect {SUCCESS, FAIL}
-
-    enum AcceptedParams {
-        EXPECT,
-        SOURCES,
-        OPTIONS,
-        STD_OUTPUT,
-        ERR_OUTPUT,
-        EXTRA_ENV,
-    }
-
-    enum OutputKind {STD, ERR}
-
-    /**
-     * Helper class to abstract the processing of command's output.
-     */
-    static abstract class WriterHelper {
-        OutputKind kind;
-        public abstract void pipeOutput(ProcessBuilder pb);
-        public abstract void readFromStream(Process p) throws IOException;
-        public abstract void addAll(Collection<? extends String> c) throws IOException;
-    }
-
-    /**
-     * Helper class for redirecting command's output to a file.
-     */
-    static class FileWriterHelper extends WriterHelper {
-        File file;
-
-        FileWriterHelper(File file, OutputKind kind) {
-            this.file = file;
-            this.kind = kind;
-        }
-
-        @Override
-        public void pipeOutput(ProcessBuilder pb) {
-            if (file != null) {
-                switch (kind) {
-                    case STD:
-                        pb.redirectInput(file);
-                        break;
-                    case ERR:
-                        pb.redirectError(file);
-                        break;
-                }
-            }
-        }
-
-        @Override
-        public void readFromStream(Process p) throws IOException {}
-
-        @Override
-        public void addAll(Collection<? extends String> c) throws IOException {
-            if (file.exists())
-                Files.write(file.toPath(), c, defaultCharset,
-                        StandardOpenOption.WRITE, StandardOpenOption.APPEND);
-            else
-                Files.write(file.toPath(), c, defaultCharset);
-        }
-    }
-
-    /**
-     * Helper class for redirecting command's output to a String list.
-     */
-    static class ListWriterHelper extends WriterHelper {
-        List<String> list;
-
-        public ListWriterHelper(List<String> list, OutputKind kind) {
-            this.kind = kind;
-            this.list = list;
-        }
-
-        @Override
-        public void pipeOutput(ProcessBuilder pb) {}
-
-        @Override
-        public void readFromStream(Process p) throws IOException {
-            BufferedReader br = null;
-            switch (kind) {
-                case STD:
-                    br = new BufferedReader(new InputStreamReader(p.getInputStream()));
-                    break;
-                case ERR:
-                    br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
-                    break;
-            }
-            String line;
-            while ((line = br.readLine()) != null) {
-                list.add(line);
-            }
-        }
-
-        public void addAll(Collection<? extends String> c) {
-            list.addAll(c);
-        }
-    }
-
-    /**
-     * Simple factory class for creating a WriterHelper instance.
-     */
-    static class WriterHelperFactory {
-        static WriterHelper make(File file, OutputKind kind) {
-            return new FileWriterHelper(file, kind);
-        }
-
-        static WriterHelper make(List<String> list, OutputKind kind) {
-            return new ListWriterHelper(list, kind);
-        }
-    }
-
-    /**
-     * A generic class for holding command's arguments.
-     */
-    public static abstract class GenericArgs <T extends GenericArgs> {
-        protected static List<Set<AcceptedParams>> minAcceptedParams;
-
-        protected Set<AcceptedParams> currentParams =
-                EnumSet.<AcceptedParams>noneOf(AcceptedParams.class);
-
-        protected Expect whatToExpect;
-        protected WriterHelper stdOutput;
-        protected WriterHelper errOutput;
-        protected List<String> args = new ArrayList<>();
-        protected String[] argsArr;
-
-        protected GenericArgs() {
-            set(Expect.SUCCESS);
-        }
-
-        public T set(Expect whatToExpt) {
-            currentParams.add(AcceptedParams.EXPECT);
-            this.whatToExpect = whatToExpt;
-            return (T)this;
-        }
-
-        public T setStdOutput(List<String> stdOutput) {
-            currentParams.add(AcceptedParams.STD_OUTPUT);
-            this.stdOutput = WriterHelperFactory.make(stdOutput, OutputKind.STD);
-            return (T)this;
-        }
-
-        public T setStdOutput(File output) {
-            currentParams.add(AcceptedParams.STD_OUTPUT);
-            this.stdOutput = WriterHelperFactory.make(output, OutputKind.STD);
-            return (T)this;
-        }
-
-        public T setErrOutput(List<String> errOutput) {
-            currentParams.add(AcceptedParams.ERR_OUTPUT);
-            this.errOutput = WriterHelperFactory.make(errOutput, OutputKind.ERR);
-            return (T)this;
-        }
-
-        public T setErrOutput(File errOutput) {
-            currentParams.add(AcceptedParams.ERR_OUTPUT);
-            this.errOutput = WriterHelperFactory.make(errOutput, OutputKind.ERR);
-            return (T)this;
-        }
-
-        public T setAllArgs(String... args) {
-            currentParams.add(AcceptedParams.OPTIONS);
-            this.argsArr = args;
-            return (T) this;
-        }
-
-
-        public T appendArgs(String... args) {
-            appendArgs(Arrays.asList(args));
-            return (T)this;
-        }
-
-        public T appendArgs(Path... args) {
-            if (args != null) {
-                List<String> list = new ArrayList<>();
-                for (int i = 0; i < args.length; i++) {
-                    if (args[i] != null) {
-                        list.add(args[i].toString());
-                    }
-                }
-                appendArgs(list);
-            }
-            return (T)this;
-        }
-
-        public T appendArgs(List<String> args) {
-            if (args != null && args.size() > 0) {
-                currentParams.add(AcceptedParams.OPTIONS);
-                for (int i = 0; i < args.size(); i++) {
-                    if (args.get(i) != null) {
-                        this.args.add(args.get(i));
-                    }
-                }
-            }
-            return (T)this;
-        }
-
-        public T setOptions(List<String> options) {
-            currentParams.add(AcceptedParams.OPTIONS);
-            this.args = options;
-            return (T)this;
-        }
-
-        public T setOptions(String... options) {
-            currentParams.add(AcceptedParams.OPTIONS);
-            this.args = Arrays.asList(options);
-            return (T)this;
-        }
-
-        public boolean hasMinParams() {
-            for (Set<AcceptedParams> minSet : minAcceptedParams) {
-                if (currentParams.containsAll(minSet)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
-     * A more specific class for holding javac-like command's arguments.
-     */
-    public static class JavaToolArgs extends GenericArgs<JavaToolArgs> {
-
-        static {
-            minAcceptedParams = new ArrayList<>();
-            minAcceptedParams.add(EnumSet.<AcceptedParams>of(
-                    AcceptedParams.EXPECT, AcceptedParams.OPTIONS));
-            minAcceptedParams.add(EnumSet.<AcceptedParams>of(
-                    AcceptedParams.EXPECT, AcceptedParams.SOURCES));
-        }
-
-        protected List<? extends JavaFileObject> sources;
-
-        public JavaToolArgs() {
-            super();
-        }
-
-        public JavaToolArgs(Expect whatToExpt) {
-            super.set(whatToExpt);
-        }
-
-        public JavaToolArgs setSources(List<? extends JavaFileObject> sources) {
-            currentParams.add(AcceptedParams.SOURCES);
-            this.sources = sources;
-            return this;
-        }
-
-        public JavaToolArgs setSources(JavaSource... sources) {
-            return setSources(Arrays.asList(sources));
-        }
-
-        public JavaToolArgs setSources(String... sources) {
-            List<JavaSource> javaSrcs = new ArrayList<>();
-            for (String source : sources) {
-                javaSrcs.add(new JavaSource(source));
-            }
-            return setSources(javaSrcs);
-        }
-    }
-
-    /**
-     * A more specific class for holding any command's arguments.
-     */
-    public static class AnyToolArgs extends GenericArgs<AnyToolArgs> {
-
-        static {
-            minAcceptedParams = new ArrayList<>();
-            minAcceptedParams.add(EnumSet.<AcceptedParams>of(
-                    AcceptedParams.EXPECT, AcceptedParams.OPTIONS));
-        }
-
-        Map<String, String> extraEnv;
-
-        public AnyToolArgs() {
-            super();
-        }
-
-        public AnyToolArgs(Expect whatToExpt) {
-            set(whatToExpt);
-        }
-
-        public AnyToolArgs set(Map<String, String> extraEnv) {
-            currentParams.add(AcceptedParams.EXTRA_ENV);
-            this.extraEnv = extraEnv;
-            return this;
-        }
-    }
-
-    /**
-     * Custom exception for bad command execution.
-     */
-    public static class CommandExecutionException extends Exception {
-        CommandExecutionException(List<String> command, Expect whatToExpt) {
-            super(createMessage(command, whatToExpt));
-        }
-
-        CommandExecutionException(Expect whatToExpt, String... command) {
-            this(Arrays.asList(command), whatToExpt);
-        }
-
-        private static String createMessage(List<String> command, Expect whatToExpt) {
-            StringBuilder sb = new StringBuilder().append("Command : ");
-            sb.append(command.toString()).append(lineSeparator);
-            switch (whatToExpt) {
-                case SUCCESS:
-                    sb.append("    has unexpectedly failed");
-                    break;
-                case FAIL:
-                    sb.append("    has been unexpectedly successful");
-                    break;
-            }
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Custom exception for not equal resources.
-     */
-    public static class ResourcesNotEqualException extends Exception {
-        public ResourcesNotEqualException(List<String> res1, List<String> res2) {
-            super(createMessage(res1, res2));
-        }
-
-        public ResourcesNotEqualException(String line1, String line2) {
-            super(createMessage(line1, line2));
-        }
-
-        public ResourcesNotEqualException(Path path1, Path path2) {
-            super(createMessage(path1, path2));
-        }
-
-        private static String createMessage(Path path1, Path path2) {
-            return new StringBuilder()
-                    .append("The resources provided for comparison in paths \n")
-                    .append(path1.toString()).append(" and \n")
-                    .append(path2.toString()).append("are different").toString();
-        }
-
-        private static String createMessage(String line1, String line2) {
-            return new StringBuilder()
-                    .append("The resources provided for comparison are different at lines: \n")
-                    .append(line1).append(" and \n")
-                    .append(line2).toString();
-        }
-
-        private static String createMessage(List<String> res1, List<String> res2) {
-            return new StringBuilder()
-                    .append("The resources provided for comparison are different: \n")
-                    .append("Resource 1 is: ").append(res1).append("\n and \n")
-                    .append("Resource 2 is: ").append(res2).append("\n").toString();
-        }
-    }
-
-    /**
-     * A javac compiler caller method.
-     */
-    public static int javac(JavaToolArgs params)
-            throws CommandExecutionException, IOException {
-        if (params.hasMinParams()) {
-            if (params.argsArr != null) {
-                return genericJavaCMD(JavaCMD.JAVAC, params);
-            } else {
-                return genericJavaCMD(JavaCMD.JAVAC_API, params);
-            }
-        }
-        throw new AssertionError("javac command has been invoked with less parameters than needed");
-    }
-
-    /**
-     * Run javac and return the resulting classfiles.
-     */
-    public static Map<String, byte[]> compile(JavaToolArgs params)
-            throws CommandExecutionException, IOException {
-        if (params.hasMinParams()) {
-            if (params.argsArr != null) {
-                throw new AssertionError("setAllArgs is not supported for compile");
-            }
-
-            StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
-            MemoryFileManager mfm = new MemoryFileManager(fm);
-            StringWriter sw = null;
-            boolean rc;
-
-            try (PrintWriter pw = (params.errOutput == null) ?
-                    null : new PrintWriter(sw = new StringWriter())) {
-                JavacTask ct = (JavacTask)comp.getTask(pw, mfm, null,
-                        params.args, null, params.sources);
-                rc = ct.call();
-            }
-
-            String out = (sw == null) ? null : sw.toString();
-
-            if (params.errOutput != null && (out != null) && !out.isEmpty()) {
-                params.errOutput.addAll(splitLines(out, lineSeparator));
-            }
-
-            if ( ( rc && params.whatToExpect == Expect.SUCCESS) ||
-                 (!rc && params.whatToExpect == Expect.FAIL) ) {
-                return mfm.classes;
-            }
-
-            throw new CommandExecutionException(JavaCMD.JAVAC_API.getExceptionMsgContent(params),
-                    params.whatToExpect);
-        }
-        throw new AssertionError("compile command has been invoked with less parameters than needed");
-    }
-
-    /**
-     * A javap calling method.
-     */
-    public static String javap(JavaToolArgs params)
-            throws CommandExecutionException, IOException {
-        if (params.hasMinParams()) {
-            List<String> list = new ArrayList<>();
-            params.setErrOutput(list);
-            genericJavaCMD(JavaCMD.JAVAP, params);
-            return listToString(list);
-        }
-        throw new AssertionError("javap command has been invoked with less parameters than needed");
-    }
-
-    /**
-     * A javah calling method.
-     */
-    public static int javah(JavaToolArgs params)
-            throws CommandExecutionException, IOException {
-        if (params.hasMinParams()) {
-            return genericJavaCMD(JavaCMD.JAVAH, params);
-        }
-        throw new AssertionError("javah command has been invoked with less parameters than needed");
-    }
-
-    /**
-     * A enum class for langtools commands.
-     */
-    enum JavaCMD {
-        JAVAC {
-            @Override
-            int run(JavaToolArgs params, PrintWriter pw) {
-                return com.sun.tools.javac.Main.compile(params.argsArr, pw);
-            }
-        },
-        JAVAC_API {
-            @Override
-            int run(JavaToolArgs params, PrintWriter pw) {
-                JavacTask ct = (JavacTask)comp.getTask(pw, null, null,
-                        params.args, null, params.sources);
-                return ((JavacTaskImpl)ct).doCall().exitCode;
-            }
-
-            @Override
-            String getName() {
-                return "javac";
-            }
-
-            @Override
-            List<String> getExceptionMsgContent(JavaToolArgs params) {
-                List<String> result = super.getExceptionMsgContent(params);
-                for (JavaFileObject source : params.sources) {
-                    if (source instanceof JavaSource) {
-                        result.add(((JavaSource)source).name);
-                    }
-                }
-                return result;
-            }
-        },
-        JAVAH {
-            @Override
-            int run(JavaToolArgs params, PrintWriter pw) {
-                return com.sun.tools.javah.Main.run(params.argsArr, pw);
-            }
-        },
-        JAVAP {
-            @Override
-            int run(JavaToolArgs params, PrintWriter pw) {
-                return com.sun.tools.javap.Main.run(params.argsArr, pw);
-            }
-        };
-
-        abstract int run(JavaToolArgs params, PrintWriter pw);
-
-        String getName() {
-            return this.name().toLowerCase();
-        }
-
-        List<String> getExceptionMsgContent(JavaToolArgs params) {
-            List<String> result = new ArrayList<>();
-            result.add(getName());
-            result.addAll(params.argsArr != null ?
-                    Arrays.asList(params.argsArr) :
-                    params.args);
-            return result;
-        }
-    }
-
-    /**
-     * A helper method for executing langtools commands.
-     */
-    private static int genericJavaCMD(
-            JavaCMD cmd,
-            JavaToolArgs params)
-            throws CommandExecutionException, IOException {
-        int rc = 0;
-        StringWriter sw = null;
-        try (PrintWriter pw = (params.errOutput == null) ?
-                null : new PrintWriter(sw = new StringWriter())) {
-            rc = cmd.run(params, pw);
-        }
-        String out = (sw == null) ? null : sw.toString();
-
-        if (params.errOutput != null && (out != null) && !out.isEmpty()) {
-            params.errOutput.addAll(splitLines(out, lineSeparator));
-        }
-
-        if ( (rc == 0 && params.whatToExpect == Expect.SUCCESS) ||
-             (rc != 0 && params.whatToExpect == Expect.FAIL) ) {
-            return rc;
-        }
-
-        throw new CommandExecutionException(cmd.getExceptionMsgContent(params),
-                params.whatToExpect);
-    }
-
-    /**
-     * A jar calling method.
-     */
-    public static boolean jar(String... params) throws CommandExecutionException {
-        Main jarGenerator = new Main(System.out, System.err, "jar");
-        boolean result = jarGenerator.run(params);
-        if (!result) {
-            List<String> command = new ArrayList<>();
-            command.add("jar");
-            command.addAll(Arrays.asList(params));
-            throw new CommandExecutionException(command, Expect.SUCCESS);
-        }
-        return result;
-    }
-
-    /**
-     * A general command calling method.
-     */
-    public static int executeCommand(AnyToolArgs params)
-            throws CommandExecutionException, IOException, InterruptedException {
-        if (params.hasMinParams()) {
-            List<String> cmd = (params.args != null) ?
-                    params.args :
-                    Arrays.asList(params.argsArr);
-            return executeCommand(cmd, params.extraEnv, params.stdOutput,
-                    params.errOutput, params.whatToExpect);
-        }
-        throw new AssertionError("command has been invoked with less parameters than needed");
-    }
-
-    /**
-     * A helper method for calling a general command.
-     */
-    private static int executeCommand(
-            List<String> command,
-            Map<String, String> extraEnv,
-            WriterHelper stdOutput,
-            WriterHelper errOutput,
-            Expect whatToExpt)
-            throws IOException, InterruptedException, CommandExecutionException {
-        ProcessBuilder pb = new ProcessBuilder(command);
-
-        if (stdOutput != null) stdOutput.pipeOutput(pb);
-        if (errOutput != null) errOutput.pipeOutput(pb);
-
-        if (extraEnv != null) {
-            pb.environment().putAll(extraEnv);
-        }
-
-        Process p = pb.start();
-
-        if (stdOutput != null) stdOutput.readFromStream(p);
-        if (errOutput != null) errOutput.readFromStream(p);
-
-        int result = p.waitFor();
-        if ( (result == 0 && whatToExpt == Expect.SUCCESS) ||
-             (result != 0 && whatToExpt == Expect.FAIL) ) {
-            return result;
-        }
-
-        throw new CommandExecutionException(command, whatToExpt);
-    }
-
-    /**
-     * This set of methods can be used instead of diff when the only needed
-     * result is the equality or inequality of the two given resources.
-     *
-     * A resource can be a file or a String list.
-     */
-    public static void compareLines(Path aPath, Path otherPath, String encoding)
-            throws FileNotFoundException, IOException, ResourcesNotEqualException {
-        compareLines(aPath, otherPath, encoding, false);
-    }
-
-    public static void compareLines(
-            Path aPath, Path otherPath, String encoding, boolean trim)
-            throws FileNotFoundException, IOException, ResourcesNotEqualException {
-        Charset charset = encoding != null ?
-                Charset.forName(encoding) :
-                defaultCharset;
-        List<String> list1 = Files.readAllLines(aPath, charset);
-        List<String> list2 = Files.readAllLines(otherPath, charset);
-        compareLines(list1, list2, trim);
-    }
-
-    public static void compareLines(Path path, List<String> strings, String encoding)
-            throws FileNotFoundException, IOException, ResourcesNotEqualException {
-        compareLines(path, strings, encoding, false);
-    }
-
-    public static void compareLines(Path path, List<String> strings,
-            String encoding, boolean trim)
-            throws FileNotFoundException, IOException, ResourcesNotEqualException {
-        Charset charset = encoding != null ?
-                Charset.forName(encoding) :
-                defaultCharset;
-        List<String> list = Files.readAllLines(path, charset);
-        compareLines(list, strings, trim);
-    }
-
-    public static void compareLines(List<String> list1, List<String> list2)
-            throws ResourcesNotEqualException {
-        compareLines(list1, list2, false);
-    }
-
-    public static void compareLines(List<String> list1,
-            List<String> list2, boolean trim) throws ResourcesNotEqualException {
-        if ((list1 == list2) || (list1 == null && list2 == null)) return;
-        if (list1.size() != list2.size())
-            throw new ResourcesNotEqualException(list1, list2);
-        int i = 0;
-        int j = 0;
-        while (i < list1.size() &&
-               j < list2.size() &&
-               equals(list1.get(i), list2.get(j), trim)) {
-            i++; j++;
-        }
-        if (!(i == list1.size() && j == list2.size()))
-            throw new ResourcesNotEqualException(list1, list2);
-    }
-
-    private static boolean equals(String s1, String s2, boolean trim) {
-        return (trim ? s1.trim().equals(s2.trim()) : s1.equals(s2));
-    }
-
-    /**
-     * A set of simple grep-like methods, looks for regExpr in text.
-     * The content of text is split using the new line character as a pattern
-     * and later the regExpr is seek in every split line. If a match is found,
-     * the whole line is added to the result.
-     */
-    public static List<String> grep(String regExpr, String text, String sep) {
-        return grep(regExpr, splitLines(text, sep));
-    }
-
-    public static List<String> grep(String regExpr, List<String> text) {
-        List<String> result = new ArrayList<>();
-        Pattern pattern = Pattern.compile(regExpr);
-        for (String s : text) {
-            if (pattern.matcher(s).find()) {
-                result.add(s);
-            }
-        }
-        return result;
-    }
-
-    public static List<String> grep(String regExpr, File f)
-            throws IOException {
-        List<String> lines = Files.readAllLines(f.toPath(), defaultCharset);
-        return grep(regExpr, lines);
-    }
-
-    /**
-     * A touch-like method.
-     */
-    public static boolean touch(String fileName) {
-        File file = new File(fileName);
-        return touch(file);
-    }
-
-    public static boolean touch(File file) {
-        if (file.exists()) {
-            file.setLastModified(System.currentTimeMillis());
-            return true;
-        }
-        return false;
-    }
-
-    public static void createJavaFile(File outFile) throws IOException {
-        createJavaFile(outFile, null);
-    }
-
-    /**
-     * A method for creating a valid but very simple java file.
-     */
-    public static void createJavaFile(File outFile, File superClass)
-            throws IOException {
-        String srcStr = "public class " + getSimpleName(outFile) + " ";
-        if (superClass != null) {
-            srcStr = srcStr.concat("extends " + getSimpleName(superClass) + " ");
-        }
-        srcStr = srcStr.concat("{}");
-        try (PrintWriter ps = new PrintWriter(new FileWriter(outFile))) {
-            ps.println(srcStr);
-        }
-    }
-
-    /**
-     * Creates a java file name given its source.
-     * The file is created in the working directory, creating a directory
-     * tree if there is a package declaration.
-     */
-    public static void createJavaFileFromSource(String source) throws IOException {
-        createJavaFileFromSource(null, source);
-    }
-
-    /**
-     * Creates a java file name given its source.
-     * The file is created in the working directory, creating a directory
-     * tree if there is a package declaration or the argument initialPath
-     * has a valid path.
-     *
-     * e.i. if initialPath is foo/ and the source is:
-     * package bar;
-     *
-     * public class bazz {}
-     *
-     * this method will create the file foo/bar/bazz.java in the working
-     * directory.
-     */
-    public static void createJavaFileFromSource(Path initialPath,
-            String source) throws IOException {
-        String fileName = getJavaFileNameFromSource(source);
-        String dirTree = getDirTreeFromSource(source);
-        Path path = (dirTree != null) ?
-                Paths.get(dirTree, fileName) :
-                Paths.get(fileName);
-        path = (initialPath != null) ?
-                initialPath.resolve(path):
-                path;
-        writeFile(path, source);
-    }
-
-    static Pattern publicClassPattern =
-            Pattern.compile("public\\s+(?:class|enum|interface){1}\\s+(\\w+)");
-    static Pattern packageClassPattern =
-            Pattern.compile("(?:class|enum|interface){1}\\s+(\\w+)");
-
-    /**
-     * Extracts the java file name from the class declaration.
-     * This method is intended for simple files and uses regular expressions,
-     * so comments matching the pattern can make the method fail.
-     */
-    static String getJavaFileNameFromSource(String source) {
-        String className = null;
-        Matcher matcher = publicClassPattern.matcher(source);
-        if (matcher.find()) {
-            className = matcher.group(1) + ".java";
-        } else {
-            matcher = packageClassPattern.matcher(source);
-            if (matcher.find()) {
-                className = matcher.group(1) + ".java";
-            } else {
-                throw new AssertionError("Could not extract the java class " +
-                        "name from the provided source");
-            }
-        }
-        return className;
-    }
-
-    static Pattern packagePattern =
-            Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))");
-
-    /**
-     * Extracts the path from the package declaration if present.
-     * This method is intended for simple files and uses regular expressions,
-     * so comments matching the pattern can make the method fail.
-     */
-    private static String getDirTreeFromSource(String source) {
-        Matcher matcher = packagePattern.matcher(source);
-        return matcher.find() ?
-            matcher.group(1).replace(".", File.separator) :
-            null;
-    }
-
-    /**
-     * A method for creating a jar's manifest file with supplied data.
-     */
-    public static void mkManifestWithClassPath(String mainClass,
-            String... classes) throws IOException {
-        List <String> lines = new ArrayList<>();
-
-        StringBuilder sb = new StringBuilder("Class-Path: ".length() +
-                classes[0].length()).append("Class-Path: ").append(classes[0]);
-        for (int i = 1; i < classes.length; i++) {
-            sb.append(" ").append(classes[i]);
-        }
-        lines.add(sb.toString());
-        if (mainClass != null) {
-            lines.add(new StringBuilder("Main-Class: ".length() +
-                      mainClass.length())
-                      .append("Main-Class: ")
-                      .append(mainClass).toString());
-        }
-        Files.write(Paths.get("MANIFEST.MF"), lines,
-                    StandardOpenOption.CREATE, StandardOpenOption.WRITE,
-                    StandardOpenOption.TRUNCATE_EXISTING);
-    }
-
-    /**
-     * A utility method to obtain the file name.
-     */
-    static String getSimpleName(File inFile) {
-        return inFile.toPath().getFileName().toString();
-    }
-
-    /**
-     * A method to write to a file, the directory tree is created if needed.
-     */
-    public static File writeFile(Path path, String body) throws IOException {
-        File result;
-        if (path.getParent() != null) {
-            Files.createDirectories(path.getParent());
-        }
-        try (FileWriter out = new FileWriter(result = path.toAbsolutePath().toFile())) {
-            out.write(body);
-        }
-        return result;
-    }
-
-    public static File writeFile(String path, String body) throws IOException {
-        return writeFile(Paths.get(path), body);
-    }
-
-    /**
-     * A rm-like method, the file is deleted only if it exists.
-     */
-    public static void rm(Path path) throws Exception {
-        Files.deleteIfExists(path);
-    }
-
-    public static void rm(String filename) throws Exception {
-        rm(Paths.get(filename));
-    }
-
-    public static void rm(File f) throws Exception {
-        rm(f.toPath());
-    }
-
-    /**
-     * Copy source file to destination file.
-     */
-    public static void copyFile(File destfile, File srcfile)
-        throws IOException {
-        copyFile(destfile.toPath(), srcfile.toPath());
-    }
-
-    public static void copyFile(Path destPath, Path srcPath)
-        throws IOException {
-        Files.createDirectories(destPath);
-        Files.copy(srcPath, destPath, REPLACE_EXISTING);
-    }
-
-    /**
-     * Splits a String using the System's line separator character as splitting point.
-     */
-    public static List<String> splitLines(String lines, String sep) {
-        return Arrays.asList(lines.split(sep));
-    }
-
-    /**
-     * Converts a String list into one String by appending the System's line separator
-     * character after each component.
-     */
-    private static String listToString(List<String> lines) {
-        StringBuilder sb = new StringBuilder();
-        for (String s : lines) {
-            sb.append(s).append(lineSeparator);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns true if the OS is a Windows version.
-     */
-    public static boolean isWindows() {
-        String osName = System.getProperty("os.name");
-        return osName.toUpperCase().startsWith("WINDOWS");
-    }
-
-    /**
-     * Class representing an in-memory java source file. It is able to extract
-     * the file name from simple source codes using regular expressions.
-     */
-    public static class JavaSource extends SimpleJavaFileObject {
-        String source;
-        String name;
-
-        public JavaSource(String className, String source) {
-            super(URI.create(className),
-                    JavaFileObject.Kind.SOURCE);
-            this.name = className;
-            this.source = source;
-        }
-
-        public JavaSource(String source) {
-            super(URI.create(getJavaFileNameFromSource(source)),
-                    JavaFileObject.Kind.SOURCE);
-            this.name = getJavaFileNameFromSource(source);
-            this.source = source;
-        }
-
-        @Override
-        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
-            return source;
-        }
-    }
-
-    /**
-     * A file manager for compiling strings to byte arrays.
-     * This file manager delegates to another file manager
-     * to lookup classes on boot class path.
-     */
-    public static final class MemoryFileManager extends ForwardingJavaFileManager {
-        /**
-         * Maps binary class names to class files stored as byte arrays.
-         */
-        private final Map<String, byte[]> classes;
-
-        /**
-         * Construct a memory file manager which delegates to the specified
-         * file manager for unknown sources.
-         * @param fileManager a file manager used to look up class files on class path, etc.
-         */
-        public MemoryFileManager(JavaFileManager fileManager) {
-            super(fileManager);
-            classes = new HashMap<>();
-        }
-
-        @java.lang.Override
-        public JavaFileObject getJavaFileForOutput(Location location,
-                                                   String name,
-                                                   Kind kind,
-                                                   FileObject sibling)
-            throws UnsupportedOperationException
-        {
-            return new JavaClassInArray(name);
-        }
-
-        /**
-         * A file object representing a Java class file stored in a byte array.
-         */
-        private class JavaClassInArray extends SimpleJavaFileObject {
-
-            private final String name;
-
-            /**
-             * Constructs a JavaClassInArray object.
-             * @param name binary name of the class to be stored in this file object
-             */
-            JavaClassInArray(String name) {
-                super(URI.create("mfm:///" + name.replace('.','/') + Kind.CLASS.extension),
-                      Kind.CLASS);
-                this.name = name;
-            }
-
-            public OutputStream openOutputStream() {
-                return new FilterOutputStream(new ByteArrayOutputStream()) {
-                    public void close() throws IOException {
-                        out.close();
-                        ByteArrayOutputStream bos = (ByteArrayOutputStream)out;
-                        classes.put(name, bos.toByteArray());
-                    }
-                };
-            }
-        }
-
-    }
-
-}
--- a/test/tools/javac/links/LinksTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/links/LinksTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 4266026
  * @summary javac no longer follows symlinks
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main LinksTest
  */
@@ -33,7 +33,7 @@
 import java.nio.file.Files;
 import java.nio.file.Paths;
 
-//original test: test/tools/javac/links/links.sh
+// Original test: test/tools/javac/links/links.sh
 public class LinksTest {
 
     private static final String BSrc =
@@ -44,20 +44,18 @@
     private static final String TSrc =
         "class T extends a.B {}";
 
-    public static void main(String args[])
-            throws Exception {
-//      mkdir tmp
-//      cp ${TESTSRC}/b/B.java tmp
-        ToolBox.writeFile(Paths.get("tmp", "B.java"), BSrc);
+    public static void main(String... args) throws Exception {
+        ToolBox tb = new ToolBox();
+        tb.writeFile("tmp/B.java", BSrc);
 
         try {
-//        ln -s `pwd`/tmp "${TESTCLASSES}/a"
             Files.createSymbolicLink(Paths.get("a"), Paths.get("tmp"));
-            ////"${TESTJAVA}/bin/javac" ${TESTTOOLVMOPTS} -sourcepath "${TESTCLASSES}" -d "${TESTCLASSES}/classes" "${TESTSRC}/T.java" 2>&1
-            ToolBox.JavaToolArgs javacArgs =
-                    new ToolBox.JavaToolArgs()
-                    .setOptions("-sourcepath", ".", "-d", ".").setSources(TSrc);
-            ToolBox.javac(javacArgs);
+
+            tb.new JavacTask()
+                    .sourcepath(".")
+                    .outdir(".")
+                    .sources(TSrc)
+                    .run();
         } catch (UnsupportedOperationException e) {
             System.err.println("Symbolic links not supported on this system. The test can't finish");
         }
--- a/test/tools/javac/newlines/NewLineTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/newlines/NewLineTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 4110560 4785453
  * @summary portability : javac.properties
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main NewLineTest
  */
@@ -39,18 +39,13 @@
 public class NewLineTest {
 
     public static void main(String args[]) throws Exception {
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -J-Dline.separator='@' > ${TMP1} 2>&1
+        ToolBox tb = new ToolBox();
         File javacErrOutput = new File("output.txt");
-        ToolBox.AnyToolArgs cmdArgs =
-                new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL)
-                .appendArgs(ToolBox.javacBinary)
-                .appendArgs(ToolBox.testToolVMOpts)
-                .appendArgs("-J-Dline.separator='@'")
-                .setErrOutput(javacErrOutput);
-        ToolBox.executeCommand(cmdArgs);
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .redirect(ToolBox.OutputKind.STDERR, javacErrOutput.getPath())
+                .options("-J-Dline.separator='@'")
+                .run(ToolBox.Expect.FAIL);
 
-//        result=`cat ${TMP1} | wc -l`
-//        if [ "$result" -eq 0 ] passed
         List<String> lines = Files.readAllLines(javacErrOutput.toPath(),
                 Charset.defaultCharset());
         if (lines.size() != 1) {
--- a/test/tools/javac/processing/rounds/CompleteOnClosed.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/processing/rounds/CompleteOnClosed.java	Wed Aug 13 13:20:31 2014 -0700
@@ -26,8 +26,8 @@
  * @bug 8038455
  * @summary Ensure that formatting diagnostics with an already closed JavaCompiler won't crash
  *          the compiler.
- * @library /tools/javac/lib
- * @build CompleteOnClosed ToolBox JavacTestingAbstractProcessor
+ * @library /tools/lib /tools/javac/lib
+ * @build ToolBox JavacTestingAbstractProcessor
  * @run main CompleteOnClosed
  */
 
--- a/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java	Wed Aug 13 13:20:31 2014 -0700
@@ -26,7 +26,7 @@
  * @bug 8038455
  * @summary Verify that annotation processor can overwrite source and class files it generated
  *          during previous compilations, and that the Symbols are updated appropriatelly.
- * @library /tools/javac/lib/
+ * @library /tools/lib /tools/javac/lib/
  * @clean *
  * @build OverwriteBetweenCompilations ToolBox JavacTestingAbstractProcessor
  * @compile/ref=OverwriteBetweenCompilations_1.out -processor OverwriteBetweenCompilations -Apass=1 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
@@ -49,6 +49,7 @@
 @SupportedOptions("pass")
 public class OverwriteBetweenCompilations extends JavacTestingAbstractProcessor {
     int round = 1;
+    @Override
     public boolean process(Set<? extends TypeElement> annotations,
                            RoundEnvironment roundEnv) {
         Log log = Log.instance(((JavacProcessingEnvironment) processingEnv).getContext());
@@ -85,11 +86,17 @@
             try (OutputStream out = filer.createClassFile("GeneratedClass").openOutputStream()) {
                 String code = pass != 2 ? GENERATED_INIT : GENERATED_UPDATE;
                 code = code.replace("NAME", "GeneratedClass");
-                ToolBox.JavaToolArgs args =
-                        new ToolBox.JavaToolArgs().appendArgs("-parameters").setSources(code);
-                Map<String, byte[]> codeMap = ToolBox.compile(args);
-                out.write(codeMap.get("GeneratedClass"));
-            } catch (IOException | ToolBox.CommandExecutionException e) {
+
+                ToolBox tb = new ToolBox();
+                ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager();
+                tb.new JavacTask()
+                        .fileManager(mfm)
+                        .options("-parameters")
+                        .sources(code)
+                        .run();
+
+                out.write(mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, "GeneratedClass"));
+            } catch (IOException e) {
                 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString());
             }
         }
--- a/test/tools/javac/stackmap/StackMapTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javac/stackmap/StackMapTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 4955930
  * @summary The "method0" StackMap attribute should have two entries instead of three
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run compile StackMapTest.java
  * @run main StackMapTest
@@ -34,7 +34,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-//original test: test/tools/javac/stackmap/T4955930.sh
+// Original test: test/tools/javac/stackmap/T4955930.sh
 public class StackMapTest {
 
     class Test {
@@ -48,16 +48,15 @@
     }
 
     public static void main(String args[]) throws Exception {
-//    "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} T4955930.java
+        ToolBox tb = new ToolBox();
+        Path pathToClass = Paths.get(ToolBox.testClasses, "StackMapTest$Test.class");
+        String javapOut = tb.new JavapTask()
+                .options("-v")
+                .classes(pathToClass.toString())
+                .run()
+                .getOutput(ToolBox.OutputKind.DIRECT);
 
-//    "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} -verbose T4955930 > ${TMP1}
-        Path pathToClass = Paths.get(System.getProperty("test.classes"),
-                "StackMapTest$Test.class");
-        ToolBox.JavaToolArgs javapArgs =
-                new ToolBox.JavaToolArgs().setAllArgs("-v", pathToClass.toString());
-
-//        grep "StackMapTable: number_of_entries = 2" ${TMP1}
-        if (!ToolBox.javap(javapArgs).contains("StackMapTable: number_of_entries = 2"))
+        if (!javapOut.contains("StackMapTable: number_of_entries = 2"))
             throw new AssertionError("The number of entries of the stack map "
                     + "table should be equal to 2");
     }
--- a/test/tools/javah/6257087/T6257087.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javah/6257087/T6257087.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,12 +25,12 @@
  * @test
  * @bug 6257087
  * @summary javah doesn't produce proper signatures for inner class native methods
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main T6257087
  */
 
-import java.nio.file.Paths;
+import java.util.List;
 
 public class T6257087 {
 
@@ -58,13 +58,14 @@
         "#endif";
 
     public static void main(String[] args) throws Exception {
-        ToolBox.JavaToolArgs javahArgs =
-                new ToolBox.JavaToolArgs()
-                .setAllArgs("-cp", System.getProperty("test.classes"), "foo");
-        ToolBox.javah(javahArgs);
+        ToolBox tb = new ToolBox();
+        tb.new JavahTask()
+                .classpath(ToolBox.testClasses)
+                .classes("foo")
+                .run();
 
-        ToolBox.compareLines(Paths.get("foo_bar.h"),
-                ToolBox.splitLines(fooBarGoldenFile, "\n"), null, true);
+        List<String> fooBarFile = tb.readAllLines("foo_bar.h");
+        tb.checkEqual(fooBarFile, tb.split(fooBarGoldenFile, "\n"));
     }
 
 }
--- a/test/tools/javah/T4942232/MissingParamClassTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javah/T4942232/MissingParamClassTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,7 +27,7 @@
  * @summary Verifies that javah won't attempt to generate a header file if a
  * native method in a supplied class contains a parameter type whose corresponding
  * class is missing or not in the classpath
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run compile MissingParamClassTest.java
  * @clean MissingParamClassException
@@ -39,32 +39,21 @@
 
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
 
-//original test: test/tools/javah/MissingParamClassTest.sh
+// Original test: test/tools/javah/MissingParamClassTest.sh
 public class MissingParamClassTest {
 
     public static void main(String[] args) throws Exception {
-        //first steps done now by jtreg
-//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java" "${TESTSRC}${FS}MissingParamClassException.java"
-//rm -f MissingParamClassException.class
+        ToolBox tb = new ToolBox();
 
-//"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1}
-        List<String> errOutput = new ArrayList<>();
-        ToolBox.JavaToolArgs javahParams =
-            new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL)
-            .setAllArgs("-classpath", System.getProperty("test.classes"), "ParamClassTest")
-            .setErrOutput(errOutput);
-        ToolBox.javah(javahParams);
+        String out = tb.new JavahTask()
+                .classpath(ToolBox.testClasses)
+                .classes("ParamClassTest")
+                .run(ToolBox.Expect.FAIL)
+                .getOutput(ToolBox.OutputKind.DIRECT);
 
-//if [ -f $GENERATED_HEADER_FILE ]; then  fail
-//if [ ! -s ${TMP1} ]; then fail
-        if (Files.exists(Paths.get("ParamClassTest.h")) || errOutput.size() == 0)
+        if (Files.exists(Paths.get("ParamClassTest.h")) || out.isEmpty())
             throw new AssertionError("The only output generated by javah must be an error message");
-        //jtreg again
-//rm -f MissingParamClassException.class ParamClassTest.class
-//rm -f $GENERATED_HEADER_FILE $TMP1
     }
 
 }
--- a/test/tools/javah/constMacroTest/ConstMacroTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javah/constMacroTest/ConstMacroTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -27,15 +27,15 @@
  * @summary Validates rewritten javah handling of class defined constants and
  * ensures that the appropriate macro definitions are placed in the generated
  * header file.
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main ConstMacroTest
  */
 
 import java.io.*;
-import java.nio.file.Paths;
+import java.util.List;
 
-//original test: test/tools/javah/ConstMacroTest.sh
+// Original test: test/tools/javah/ConstMacroTest.sh
 public class ConstMacroTest {
 
     private static final String subClassConstsGoldenFileTemplate =
@@ -71,27 +71,21 @@
         "#endif\n" +
         "#endif";
 
-    private static final String serialVersionUIDSuffix =
-            ToolBox.isWindows() ? "i64" : "LL"; ;
+    public static void main(String[] args) throws Exception {
+        ToolBox tb = new ToolBox();
 
-    public static void main(String[] args) throws Exception {
-        //first steps are now done by jtreg
-//        cp "${TESTSRC}${FS}SuperClassConsts.java" .
-//        cp "${TESTSRC}${FS}SubClassConsts.java" .
+        tb.new JavahTask()
+                .classpath(ToolBox.testClasses)
+                .classes("SubClassConsts")
+                .run();
 
-//        "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}SubClassConsts.java"
+        String longSuffix = tb.isWindows() ? "i64" : "LL";
+        List<String> subClassConstsGoldenFile = tb.split(
+                String.format(subClassConstsGoldenFileTemplate, longSuffix), "\n");
 
-//        "${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} SubClassConsts
-        ToolBox.JavaToolArgs successParams =
-                new ToolBox.JavaToolArgs()
-                .setAllArgs("-cp", System.getProperty("test.classes"), "SubClassConsts");
-        ToolBox.javah(successParams);
+        List<String> subClassConstsFile = tb.readAllLines("SubClassConsts.h");
 
-//        diff ${DIFFOPTS} "${TESTSRC}${FS}${EXPECTED_JAVAH_OUT_FILE}" "${GENERATED_HEADER_FILE}"
-        String subClassConstGoldenFile = String.format(subClassConstsGoldenFileTemplate,
-                serialVersionUIDSuffix);
-        ToolBox.compareLines(Paths.get("SubClassConsts.h"),
-                ToolBox.splitLines(subClassConstGoldenFile, "\n"), null, true);
+        tb.checkEqual(subClassConstsFile, subClassConstsGoldenFile);
     }
 
 }
--- a/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -24,19 +24,23 @@
 /*
  * @test
  * @bug 4798312
- * @summary In Windows, javap doesnt load classes from rt.jar
- * @library /tools/javac/lib
+ * @summary In Windows, javap doesn't load classes from rt.jar
+ * @library /tools/lib
  * @build ToolBox
  * @run main JavapShouldLoadClassesFromRTJarTest
  */
+
 public class JavapShouldLoadClassesFromRTJarTest {
 
     public static void main(String[] args) throws Exception {
-//        "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} java.lang.String
-        ToolBox.JavaToolArgs params =
-                new ToolBox.JavaToolArgs().
-                setAllArgs("-v", "java.lang.String");
-        if (ToolBox.javap(params).isEmpty())
+        ToolBox tb = new ToolBox();
+        String out = tb.new JavapTask()
+                .options("-v")
+                .classes("java.lang.String")
+                .run()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (out.isEmpty())
             throw new AssertionError("javap generated no output");
     }
 
--- a/test/tools/javap/4866831/PublicInterfaceTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javap/4866831/PublicInterfaceTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,9 +1,5 @@
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -29,23 +25,29 @@
  * @test
  * @bug 4866831
  * @summary Verify that javap marks public interfaces as public
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main PublicInterfaceTest
  */
 
-//original test: test/tools/javap/PublicInterfaceTest.sh
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+// Original test: test/tools/javap/PublicInterfaceTest.sh
 public class PublicInterfaceTest {
     public interface Test {}
 
     public static void main(String[] args) throws Exception {
-//        "$JAVAP" ${TESTTOOLVMOPTS} -classpath "${TESTCLASSES}" NotPackagePrivateInterface | grep public
-        Path pathToClass = Paths.get(System.getProperty("test.classes"),
-                "PublicInterfaceTest$Test.class");
-        ToolBox.JavaToolArgs javapParams =
-                new ToolBox.JavaToolArgs()
-                .setAllArgs(pathToClass.toString());
-        if (!ToolBox.javap(javapParams).contains("public"))
+        ToolBox tb = new ToolBox();
+
+        Path pathToClass = Paths.get(ToolBox.testClasses, "PublicInterfaceTest$Test.class");
+
+        String out = tb.new JavapTask()
+                .classes(pathToClass.toString())
+                .run()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!out.contains("public"))
             throw new AssertionError("The javap output does not contain \"public\"");
     }
 
--- a/test/tools/javap/stackmap/StackmapTest.java	Wed Aug 13 14:25:46 2014 -0400
+++ b/test/tools/javap/stackmap/StackmapTest.java	Wed Aug 13 13:20:31 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -25,15 +25,15 @@
  * @test
  * @bug 6271292
  * @summary Verify that javap prints StackMapTable attribute contents
- * @library /tools/javac/lib
+ * @library /tools/lib
  * @build ToolBox
  * @run main StackmapTest
  */
 
-import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.List;
 
-//original test: test/tools/javap/stackmap/T6271292.sh
+// Original test: test/tools/javap/stackmap/T6271292.sh
 public class StackmapTest {
 
     private static final String TestSrc =
@@ -58,41 +58,42 @@
         "}\n";
 
     private static final String goldenOut =
-        "frame_type = 255 /* full_frame */\n" +
-        "frame_type = 255 /* full_frame */\n" +
-        "frame_type = 73 /* same_locals_1_stack_item */\n" +
-        "frame_type = 255 /* full_frame */\n" +
-        "offset_delta = 19\n" +
-        "offset_delta = 0\n" +
-        "offset_delta = 2\n" +
-        "stack = [ uninitialized 0, uninitialized 0 ]\n" +
-        "stack = [ uninitialized 0, uninitialized 0, double ]\n" +
-        "stack = [ this ]\n" +
-        "stack = [ this, double ]\n" +
-        "locals = [ class \"[Ljava/lang/String;\" ]\n" +
-        "locals = [ class \"[Ljava/lang/String;\" ]\n" +
-        "locals = [ this, int ]\n";
+        "        frame_type = 255 /* full_frame */\n" +
+        "        frame_type = 255 /* full_frame */\n" +
+        "        frame_type = 73 /* same_locals_1_stack_item */\n" +
+        "        frame_type = 255 /* full_frame */\n" +
+        "          offset_delta = 19\n" +
+        "          offset_delta = 0\n" +
+        "          offset_delta = 2\n" +
+        "          stack = [ uninitialized 0, uninitialized 0 ]\n" +
+        "          stack = [ uninitialized 0, uninitialized 0, double ]\n" +
+        "          stack = [ this ]\n" +
+        "          stack = [ this, double ]\n" +
+        "          locals = [ class \"[Ljava/lang/String;\" ]\n" +
+        "          locals = [ class \"[Ljava/lang/String;\" ]\n" +
+        "          locals = [ this, int ]\n";
 
     public static void main(String[] args) throws Exception {
-        //        @compile T6271292.java
-        ToolBox.JavaToolArgs javacParams =
-                new ToolBox.JavaToolArgs().setSources(TestSrc);
-        ToolBox.javac(javacParams);
+        ToolBox tb = new ToolBox();
 
-//        "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} -classpath "${TESTCLASSES}" -verbose T6271292 > "${JAVAPFILE}"
-        ToolBox.JavaToolArgs javapParams =
-                new ToolBox.JavaToolArgs()
-                .setAllArgs("-v", "Test.class");
-        String out = ToolBox.javap(javapParams);
-        List<String> grepResult = ToolBox.grep("frame_type", out,
-                ToolBox.lineSeparator);
-        grepResult.addAll(ToolBox.grep("offset_delta", out, ToolBox.lineSeparator));
-        grepResult.addAll(ToolBox.grep("stack = ", out, ToolBox.lineSeparator));
-        grepResult.addAll(ToolBox.grep("locals = ", out, ToolBox.lineSeparator));
-        List<String> goldenList = Arrays.asList(goldenOut.split("\n"));
+        tb.new JavacTask()
+                .sources(TestSrc)
+                .run();
 
-//        diff -w "${OUTFILE}" "${TESTSRC}${FS}T6271292.out"
-        ToolBox.compareLines(goldenList, grepResult, true);
+        List<String> out = tb.new JavapTask()
+                .options("-v")
+                .classes("Test.class")
+                .run()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> grepResult = new ArrayList<>();
+        grepResult.addAll(tb.grep("frame_type",   out));
+        grepResult.addAll(tb.grep("offset_delta", out));
+        grepResult.addAll(tb.grep("stack = ",     out));
+        grepResult.addAll(tb.grep("locals = ",    out));
+
+        List<String> goldenList = tb.split(goldenOut, "\n");
+        tb.checkEqual(goldenList, grepResult);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/lib/ToolBox.java	Wed Aug 13 13:20:31 2014 -0700
@@ -0,0 +1,1920 @@
+/*
+ * Copyright (c) 2013, 2014, 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 java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FilterOutputStream;
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.api.JavacTool;
+import java.io.IOError;
+
+/**
+ * Utility methods and classes for writing jtreg tests for
+ * javac, javah, javap, and sjavac. (For javadoc support,
+ * see JavadocTester.)
+ *
+ * <p>There is support for common file operations similar to
+ * shell commands like cat, cp, diff, mv, rm, grep.
+ *
+ * <p>There is also support for invoking various tools, like
+ * javac, javah, javap, jar, java and other JDK tools.
+ *
+ * <p><em>File separators</em>: for convenience, many operations accept strings
+ * to represent filenames. On all platforms on which JDK is supported,
+ * "/" is a legal filename component separator. In particular, even
+ * on Windows, where the official file separator is "\", "/" is a legal
+ * alternative. It is therefore recommended that any client code using
+ * strings to specify filenames should use "/".
+ *
+ * @author Vicente Romero (original)
+ * @author Jonathan Gibbons (revised)
+ */
+public class ToolBox {
+    /** The platform line separator. */
+    public static final String lineSeparator = System.getProperty("line.separator");
+    /** The platform OS name. */
+    public static final String osName = System.getProperty("os.name");
+
+    /** The location of the class files for this test, or null if not set. */
+    public static final String testClasses = System.getProperty("test.classes");
+    /** The location of the source files for this test, or null if not set. */
+    public static final String testSrc = System.getProperty("test.src");
+    /** The location of the test JDK for this test, or null if not set. */
+    public static final String testJDK = System.getProperty("test.jdk");
+
+    /** The current directory. */
+    public static final Path currDir = Paths.get(".");
+
+    /** The stream used for logging output. */
+    public PrintStream out = System.err;
+
+    JavaCompiler compiler;
+    StandardJavaFileManager standardJavaFileManager;
+
+    /**
+     * Checks if the host OS is some version of Windows.
+     * @return true if the host OS is some version of Windows
+     */
+    public boolean isWindows() {
+        return osName.toLowerCase(Locale.ENGLISH).startsWith("windows");
+    }
+
+    /**
+     * Splits a string around matches of the given regular expression.
+     * If the string is empty, an empty list will be returned.
+     * @param text the string to be split
+     * @param sep  the delimiting regular expression
+     * @return the strings between the separators
+     */
+    public List<String> split(String text, String sep) {
+        if (text.isEmpty())
+            return Collections.emptyList();
+        return Arrays.asList(text.split(sep));
+    }
+
+    /**
+     * Checks if two lists of strings are equal.
+     * @param l1 the first list of strings to be compared
+     * @param l2 the second list of strings to be compared
+     * @throws Error if the lists are not equal
+     */
+    public void checkEqual(List<String> l1, List<String> l2) throws Error {
+        if (!Objects.equals(l1, l2)) {
+            // l1 and l2 cannot both be null
+            if (l1 == null)
+                throw new Error("comparison failed: l1 is null");
+            if (l2 == null)
+                throw new Error("comparison failed: l2 is null");
+            // report first difference
+            for (int i = 0; i < Math.min(l1.size(), l2.size()); i++) {
+                String s1 = l1.get(i);
+                String s2 = l1.get(i);
+                if (!Objects.equals(s1, s2)) {
+                    throw new Error("comparison failed, index " + i +
+                            ", (" + s1 + ":" + s2 + ")");
+                }
+            }
+            throw new Error("comparison failed: l1.size=" + l1.size() + ", l2.size=" + l2.size());
+        }
+    }
+
+    /**
+     * Filters a list of strings according to the given regular expression.
+     * @param regex the regular expression
+     * @param lines the strings to be filtered
+     * @return the strings matching the regular expression
+     */
+    public List<String> grep(String regex, List<String> lines) {
+        return grep(Pattern.compile(regex), lines);
+    }
+
+    /**
+     * Filters a list of strings according to the given regular expression.
+     * @param pattern the regular expression
+     * @param lines the strings to be filtered
+     * @return the strings matching the regular expression
+     */
+    public List<String> grep(Pattern pattern, List<String> lines) {
+        return lines.stream()
+                .filter(s -> pattern.matcher(s).find())
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Copies a file.
+     * If the given destination exists and is a directory, the copy is created
+     * in that directory.  Otherwise, the copy will be placed at the destination,
+     * possibly overwriting any existing file.
+     * <p>Similar to the shell "cp" command: {@code cp from to}.
+     * @param from the file to be copied
+     * @param to where to copy the file
+     * @throws IOException if any error occurred while copying the file
+     */
+    public void copyFile(String from, String to) throws IOException {
+        copyFile(Paths.get(from), Paths.get(to));
+    }
+
+    /**
+     * Copies a file.
+     * If the given destination exists and is a directory, the copy is created
+     * in that directory.  Otherwise, the copy will be placed at the destination,
+     * possibly overwriting any existing file.
+     * <p>Similar to the shell "cp" command: {@code cp from to}.
+     * @param from the file to be copied
+     * @param to where to copy the file
+     * @throws IOException if an error occurred while copying the file
+     */
+    public void copyFile(Path from, Path to) throws IOException {
+        if (Files.isDirectory(to)) {
+            to = to.resolve(from.getFileName());
+        } else {
+            Files.createDirectories(to.getParent());
+        }
+        Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    /**
+     * Creates one of more directories.
+     * For each of the series of paths, a directory will be created,
+     * including any necessary parent directories.
+     * <p>Similar to the shell command: {@code mkdir -p paths}.
+     * @param paths the directories to be created
+     * @throws IOException if an error occurred while creating the directories
+     */
+    public void createDirectories(String... paths) throws IOException {
+        if (paths.length == 0)
+            throw new IllegalArgumentException("no directories specified");
+        for (String p: paths)
+            Files.createDirectories(Paths.get(p));
+    }
+
+    /**
+     * Creates one or more directories.
+     * For each of the series of paths, a directory will be created,
+     * including any necessary parent directories.
+     * <p>Similar to the shell command: {@code mkdir -p paths}.
+     * @param paths the directories to be created
+     * @throws IOException if an error occurred while creating the directories
+     */
+    public void createDirectories(Path... paths) throws IOException {
+        if (paths.length == 0)
+            throw new IllegalArgumentException("no directories specified");
+        for (Path p: paths)
+            Files.createDirectories(p);
+    }
+
+    /**
+     * Deletes one or more files.
+     * Any directories to be deleted must be empty.
+     * <p>Similar to the shell command: {@code rm files}.
+     * @param files the files to be deleted
+     * @throws IOException if an error occurred while deleting the files
+     */
+    public void deleteFiles(String... files) throws IOException {
+        if (files.length == 0)
+            throw new IllegalArgumentException("no files specified");
+        for (String file: files)
+            Files.delete(Paths.get(file));
+    }
+
+    /**
+     * Moves a file.
+     * If the given destination exists and is a directory, the file will be moved
+     * to that directory.  Otherwise, the file will be moved to the destination,
+     * possibly overwriting any existing file.
+     * <p>Similar to the shell "mv" command: {@code mv from to}.
+     * @param from the file to be moved
+     * @param to where to move the file
+     * @throws IOException if an error occurred while moving the file
+     */
+    public void moveFile(String from, String to) throws IOException {
+        moveFile(Paths.get(from), Paths.get(to));
+    }
+
+    /**
+     * Moves a file.
+     * If the given destination exists and is a directory, the file will be moved
+     * to that directory.  Otherwise, the file will be moved to the destination,
+     * possibly overwriting any existing file.
+     * <p>Similar to the shell "mv" command: {@code mv from to}.
+     * @param from the file to be moved
+     * @param to where to move the file
+     * @throws IOException if an error occurred while moving the file
+     */
+    public void moveFile(Path from, Path to) throws IOException {
+        if (Files.isDirectory(to)) {
+            to = to.resolve(from.getFileName());
+        } else {
+            Files.createDirectories(to.getParent());
+        }
+        Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    /**
+     * Reads the lines of a file.
+     * The file is read using the default character encoding.
+     * @param path the file to be read
+     * @return the lines of the file.
+     * @throws IOException if an error occurred while reading the file
+     */
+    public List<String> readAllLines(String path) throws IOException {
+        return readAllLines(path, null);
+    }
+
+    /**
+     * Reads the lines of a file.
+     * The file is read using the default character encoding.
+     * @param path the file to be read
+     * @return the lines of the file.
+     * @throws IOException if an error occurred while reading the file
+     */
+    public List<String> readAllLines(Path path) throws IOException {
+        return readAllLines(path, null);
+    }
+
+    /**
+     * Reads the lines of a file using the given encoding.
+     * @param path the file to be read
+     * @param encoding the encoding to be used to read the file
+     * @return the lines of the file.
+     * @throws IOException if an error occurred while reading the file
+     */
+    public List<String> readAllLines(String path, String encoding) throws IOException {
+        return readAllLines(Paths.get(path), encoding);
+    }
+
+    /**
+     * Reads the lines of a file using the given encoding.
+     * @param path the file to be read
+     * @param encoding the encoding to be used to read the file
+     * @return the lines of the file.
+     * @throws IOException if an error occurred while reading the file
+     */
+    public List<String> readAllLines(Path path, String encoding) throws IOException {
+        return Files.readAllLines(path, getCharset(encoding));
+    }
+
+    private Charset getCharset(String encoding) {
+        return (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding);
+    }
+
+    /**
+     * Writes a file containing the given content.
+     * Any necessary directories for the file will be created.
+     * @param path where to write the file
+     * @param content the content for the file
+     * @throws IOException if an error occurred while writing the file
+     */
+    public void writeFile(String path, String content) throws IOException {
+        writeFile(Paths.get(path), content);
+    }
+
+    /**
+     * Writes a file containing the given content.
+     * Any necessary directories for the file will be created.
+     * @param path where to write the file
+     * @param content the content for the file
+     * @throws IOException if an error occurred while writing the file
+     */
+    public void writeFile(Path path, String content) throws IOException {
+        Path dir = path.getParent();
+        if (dir != null)
+            Files.createDirectories(dir);
+        try (BufferedWriter w = Files.newBufferedWriter(path)) {
+            w.write(content);
+        }
+    }
+
+    /**
+     * Writes one or more files containing Java source code.
+     * For each file to be written, the filename will be inferred from the
+     * given base directory, the package declaration (if present) and from the
+     * the name of the first class, interface or enum declared in the file.
+     * <p>For example, if the base directory is /my/dir/ and the content
+     * contains "package p; class C { }", the file will be written to
+     * /my/dir/p/C.java.
+     * <p>Note: the content is analyzed using regular expressions;
+     * errors can occur if any contents have initial comments that might trip
+     * up the analysis.
+     * @param dir the base directory
+     * @param contents the contents of the files to be written
+     * @throws IOException if an error occurred while writing any of the files.
+     */
+    public void writeJavaFiles(Path dir, String... contents) throws IOException {
+        if (contents.length == 0)
+            throw new IllegalArgumentException("no content specified for any files");
+        for (String c: contents) {
+            new JavaSource(c).write(dir);
+        }
+    }
+
+    /**
+     * Returns the path for the binary of a JDK tool within {@link testJDK}.
+     * @param tool the name of the tool
+     * @return the path of the tool
+     */
+    public Path getJDKTool(String tool) {
+        return Paths.get(testJDK, "bin", tool);
+    }
+
+    /**
+     * Returns a string representing the contents of an {@code Iterable} as a list.
+     * @param <T> the type parameter of the {@code Iterable}
+     * @param items the iterable
+     * @return the string
+     */
+    <T> String toString(Iterable<T> items) {
+        return StreamSupport.stream(items.spliterator(), false)
+                .map(Objects::toString)
+                .collect(Collectors.joining(",", "[", "]"));
+    }
+
+    /**
+     * The supertype for tasks.
+     * Complex operations are modelled by building and running a "Task" object.
+     * Tasks are typically configured in a fluent series of calls.
+     */
+    public interface Task {
+        /**
+         * Returns the name of the task.
+         * @return the name of the task
+         */
+        String name();
+
+        /**
+         * Executes the task as currently configured.
+         * @return a Result object containing the results of running the task
+         * @throws TaskError if the outcome of the task was not as expected
+         */
+        Result run() throws TaskError;
+    }
+
+    /**
+     * Exception thrown by {@code Task.run} when the outcome is not as
+     * expected.
+     */
+    public static class TaskError extends Error {
+        /**
+         * Creates a TaskError object with the given message.
+         * @param message the message
+         */
+        public TaskError(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * An enum to indicate the mode a task should use it is when executed.
+     */
+    public enum Mode {
+        /**
+         * The task should use the interface used by the command
+         * line launcher for the task.
+         * For example, for javac: com.sun.tools.javac.Main.compile
+         */
+        CMDLINE,
+        /**
+         * The task should use a publicly defined API for the task.
+         * For example, for javac: javax.tools.JavaCompiler
+         */
+        API,
+        /**
+         * The task should use the standard launcher for the task.
+         * For example, $JAVA_HOME/bin/javac
+         */
+        EXEC
+    }
+
+    /**
+     * An enum to indicate the expected success or failure of executing a task.
+     */
+    public enum Expect {
+        /** It is expected that the task will complete successfully. */
+        SUCCESS,
+        /** It is expected that the task will not complete successfully. */
+        FAIL
+    }
+
+    /**
+     * An enum to identify the streams that may be written by a {@code Task}.
+     */
+    public enum OutputKind {
+        /** Identifies output written to {@code System.out} or {@code stdout}. */
+        STDOUT,
+        /** Identifies output written to {@code System.err} or {@code stderr}. */
+        STDERR,
+        /** Identifies output written to a stream provided directly to the task. */
+        DIRECT
+    };
+
+    /**
+     * The results from running a {@link Task}.
+     * The results contain the exit code returned when the tool was invoked,
+     * and a map containing the output written to any streams during the
+     * execution of the tool.
+     * All tools support "stdout" and "stderr".
+     * Tools that take an explicit PrintWriter save output written to that
+     * stream as "main".
+     */
+    public class Result {
+
+        final Task task;
+        final int exitCode;
+        final Map<OutputKind, String> outputMap;
+
+        Result(Task task, int exitCode, Map<OutputKind, String> outputMap) {
+            this.task = task;
+            this.exitCode = exitCode;
+            this.outputMap = outputMap;
+        }
+
+        /**
+         * Returns the content of a specified stream.
+         * @param outputKind the kind of the selected stream
+         * @return the content that was written to that stream when the tool
+         *  was executed.
+         */
+        public String getOutput(OutputKind outputKind) {
+            return outputMap.get(outputKind);
+        }
+
+        /**
+         * Returns the content of a named stream as a list of lines.
+         * @param outputKind the kind of the selected stream
+         * @return the content that was written to that stream when the tool
+         *  was executed.
+         */
+        public List<String> getOutputLines(OutputKind outputKind) {
+            return Arrays.asList(outputMap.get(outputKind).split(lineSeparator));
+        }
+
+        /**
+         * Writes the content of the specified stream to the log.
+         * @param kind the kind of the selected stream
+         * @return this Result object
+         */
+        public Result write(OutputKind kind) {
+            String text = getOutput(kind);
+            if (text == null || text.isEmpty())
+                out.println("[" + task.name() + ":" + kind + "]: empty");
+            else {
+                out.println("[" + task.name() + ":" + kind + "]:");
+                out.print(text);
+            }
+            return this;
+        }
+
+        /**
+         * Writes the content of all streams with any content to the log.
+         * @return this Result object
+         */
+        public Result writeAll() {
+            outputMap.forEach((name, text) -> {
+                if (!text.isEmpty()) {
+                    out.println("[" + name + "]:");
+                    out.print(text);
+                }
+            });
+            return this;
+        }
+    }
+
+    /**
+     * A utility base class to simplify the implementation of tasks.
+     * Provides support for running the task in a process and for
+     * capturing output written by the task to stdout, stderr and
+     * other writers where applicable.
+     * @param <T> the implementing subclass
+     */
+    protected static abstract class AbstractTask<T extends AbstractTask<T>> implements Task {
+        protected final Mode mode;
+        private final Map<OutputKind, String> redirects = new EnumMap<>(OutputKind.class);
+        private final Map<String, String> envVars = new HashMap<>();
+        private Expect expect = Expect.SUCCESS;
+        int expectedExitCode = 0;
+
+        /**
+         * Create a task that will execute in the specified mode.
+         * @param mode the mode
+         */
+        protected AbstractTask(Mode mode) {
+            this.mode = mode;
+        }
+
+        /**
+         * Sets the expected outcome of the task and calls {@code run()}.
+         * @param expect the expected outcome
+         * @return the result of calling {@code run()}
+         */
+        public Result run(Expect expect) {
+            expect(expect, Integer.MIN_VALUE);
+            return run();
+        }
+
+        /**
+         * Sets the expected outcome of the task and calls {@code run()}.
+         * @param expect the expected outcome
+         * @param exitCode the expected exit code if the expected outcome
+         *      is {@code FAIL}
+         * @return the result of calling {@code run()}
+         */
+        public Result run(Expect expect, int exitCode) {
+            expect(expect, exitCode);
+            return run();
+        }
+
+        /**
+         * Sets the expected outcome and expected exit code of the task.
+         * The exit code will not be checked if the outcome is
+         * {@code Expect.SUCCESS} or if the exit code is set to
+         * {@code Integer.MIN_VALUE}.
+         * @param expect the expected outcome
+         * @param exitCode the expected exit code
+         */
+        protected void expect(Expect expect, int exitCode) {
+            this.expect = expect;
+            this.expectedExitCode = exitCode;
+        }
+
+        /**
+         * Checks the exit code contained in a {@code Result} against the
+         * expected outcome and exit value
+         * @param result the result object
+         * @return the result object
+         * @throws TaskError if the exit code stored in the result object
+         *      does not match the expected outcome and exit code.
+         */
+        protected Result checkExit(Result result) throws TaskError {
+            switch (expect) {
+                case SUCCESS:
+                    if (result.exitCode != 0) {
+                        result.writeAll();
+                        throw new TaskError("Task " + name() + " failed: rc=" + result.exitCode);
+                    }
+                    break;
+
+                case FAIL:
+                    if (result.exitCode == 0) {
+                        result.writeAll();
+                        throw new TaskError("Task " + name() + " succeeded unexpectedly");
+                    }
+
+                    if (expectedExitCode != Integer.MIN_VALUE
+                            && result.exitCode != expectedExitCode) {
+                        result.writeAll();
+                        throw new TaskError("Task " + name() + "failed with unexpected exit code "
+                            + result.exitCode + ", expected " + expectedExitCode);
+                    }
+                    break;
+            }
+            return result;
+        }
+
+        /**
+         * Sets an environment variable to be used by this task.
+         * @param name the name of the environment variable
+         * @param value the value for the environment variable
+         * @return this task object
+         * @throws IllegalStateException if the task mode is not {@code EXEC}
+         */
+        protected T envVar(String name, String value) {
+            if (mode != Mode.EXEC)
+                throw new IllegalStateException();
+            envVars.put(name, value);
+            return (T) this;
+        }
+
+        /**
+         * Redirects output from an output stream to a file.
+         * @param outputKind the name of the stream to be redirected.
+         * @param path the file
+         * @return this task object
+         * @throws IllegalStateException if the task mode is not {@code EXEC}
+         */
+        protected T redirect(OutputKind outputKind, String path) {
+            if (mode != Mode.EXEC)
+                throw new IllegalStateException();
+            redirects.put(outputKind, path);
+            return (T) this;
+        }
+
+        /**
+         * Returns a {@code ProcessBuilder} initialized with any
+         * redirects and environment variables that have been set.
+         * @return a {@code ProcessBuilder}
+         */
+        protected ProcessBuilder getProcessBuilder() {
+            if (mode != Mode.EXEC)
+                throw new IllegalStateException();
+            ProcessBuilder pb = new ProcessBuilder();
+            if (redirects.get(OutputKind.STDOUT) != null)
+                pb.redirectOutput(new File(redirects.get(OutputKind.STDOUT)));
+            if (redirects.get(OutputKind.STDERR) != null)
+                pb.redirectError(new File(redirects.get(OutputKind.STDERR)));
+            pb.environment().putAll(envVars);
+            return pb;
+        }
+
+        /**
+         * Collects the output from a process and saves it in a {@code Result}.
+         * @param tb the {@code ToolBox} containing the task {@code t}
+         * @param t the task initiating the process
+         * @param p the process
+         * @return a Result object containing the output from the process and its
+         *      exit value.
+         * @throws InterruptedException if the thread is interrupted
+         */
+        protected Result runProcess(ToolBox tb, Task t, Process p) throws InterruptedException {
+            if (mode != Mode.EXEC)
+                throw new IllegalStateException();
+            ProcessOutput sysOut = new ProcessOutput(p.getInputStream()).start();
+            ProcessOutput sysErr = new ProcessOutput(p.getErrorStream()).start();
+            sysOut.waitUntilDone();
+            sysErr.waitUntilDone();
+            int rc = p.waitFor();
+            Map<OutputKind, String> outputMap = new EnumMap<>(OutputKind.class);
+            outputMap.put(OutputKind.STDOUT, sysOut.getOutput());
+            outputMap.put(OutputKind.STDERR, sysErr.getOutput());
+            return checkExit(tb.new Result(t, rc, outputMap));
+        }
+
+        /**
+         * Thread-friendly class to read the output from a process until the stream
+         * is exhausted.
+         */
+        static class ProcessOutput implements Runnable {
+            ProcessOutput(InputStream from) {
+                in = new BufferedReader(new InputStreamReader(from));
+                out = new StringBuilder();
+            }
+
+            ProcessOutput start() {
+                new Thread(this).start();
+                return this;
+            }
+
+            @Override
+            public void run() {
+                try {
+                    String line;
+                    while ((line = in.readLine()) != null) {
+                        out.append(line).append("\n");
+                    }
+                } catch (IOException e) {
+                }
+                synchronized (this) {
+                    done = true;
+                    notifyAll();
+                }
+            }
+
+            synchronized void waitUntilDone() throws InterruptedException {
+                boolean interrupted = false;
+
+                // poll interrupted flag, while waiting for copy to complete
+                while (!(interrupted = Thread.interrupted()) && !done)
+                    wait(1000);
+
+                if (interrupted)
+                    throw new InterruptedException();
+            }
+
+            String getOutput() {
+                return out.toString();
+            }
+
+            private BufferedReader in;
+            private final StringBuilder out;
+            private boolean done;
+        }
+
+        /**
+         * Utility class to simplify the handling of temporarily setting a
+         * new stream for System.out or System.err.
+         */
+        static class StreamOutput {
+            // Functional interface to set a stream.
+            // Expected use: System::setOut, System::setErr
+            private interface Initializer {
+                void set(PrintStream s);
+            }
+
+            private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            private final PrintStream ps = new PrintStream(baos);
+            private final PrintStream prev;
+            private final Initializer init;
+
+            StreamOutput(PrintStream s, Initializer init) {
+                prev = s;
+                init.set(ps);
+                this.init = init;
+            }
+
+            /**
+             * Closes the stream and returns the contents that were written to it.
+             * @return the contents that were written to it.
+             */
+            String close() {
+                init.set(prev);
+                ps.close();
+                return baos.toString();
+            }
+        }
+
+        /**
+         * Utility class to simplify the handling of creating an in-memory PrintWriter.
+         */
+        static class WriterOutput {
+            private final StringWriter sw = new StringWriter();
+            final PrintWriter pw = new PrintWriter(sw);
+
+            /**
+             * Closes the stream and returns the contents that were written to it.
+             * @return the contents that were written to it.
+             */
+            String close() {
+                pw.close();
+                return sw.toString();
+            }
+        }
+    }
+
+    /**
+     * A task to configure and run the Java compiler, javac.
+     */
+    public class JavacTask extends AbstractTask<JavacTask> {
+        private boolean includeStandardOptions;
+        private String classpath;
+        private String sourcepath;
+        private String outdir;
+        private List<String> options;
+        private List<String> classes;
+        private List<String> files;
+        private List<JavaFileObject> fileObjects;
+        private JavaFileManager fileManager;
+
+        /**
+         * Creates a task to execute {@code javac} using API mode.
+         */
+        public JavacTask() {
+            super(Mode.API);
+        }
+
+        /**
+         * Creates a task to execute {@code javac} in a specified mode.
+         * @param mode the mode to be used
+         */
+        public JavacTask(Mode mode) {
+            super(mode);
+        }
+
+        /**
+         * Sets the classpath.
+         * @param classpath the classpath
+         * @return this task object
+         */
+        public JavacTask classpath(String classpath) {
+            this.classpath = classpath;
+            return this;
+        }
+
+        /**
+         * Sets the sourcepath.
+         * @param sourcepath the sourcepath
+         * @return this task object
+         */
+        public JavacTask sourcepath(String sourcepath) {
+            this.sourcepath = sourcepath;
+            return this;
+        }
+
+        /**
+         * Sets the output directory.
+         * @param outdir the output directory
+         * @return this task object
+         */
+        public JavacTask outdir(String outdir) {
+            this.outdir = outdir;
+            return this;
+        }
+
+        /**
+         * Sets the options.
+         * @param options the options
+         * @return this task object
+         */
+        public JavacTask options(String... options) {
+            this.options = Arrays.asList(options);
+            return this;
+        }
+
+        /**
+         * Sets the classes to be analyzed.
+         * @param classes the classes
+         * @return this task object
+         */
+        public JavacTask classes(String... classes) {
+            this.classes = Arrays.asList(classes);
+            return this;
+        }
+
+        /**
+         * Sets the files to be compiled or analyzed.
+         * @param files the files
+         * @return this task object
+         */
+        public JavacTask files(String... files) {
+            this.files = Arrays.asList(files);
+            return this;
+        }
+
+        /**
+         * Sets the files to be compiled or analyzed.
+         * @param files the files
+         * @return this task object
+         */
+        public JavacTask files(Path... files) {
+            this.files = Stream.of(files)
+                    .map(Path::toString)
+                    .collect(Collectors.toList());
+            return this;
+        }
+
+        /**
+         * Sets the sources to be compiled or analyzed.
+         * Each source string is converted into an in-memory object that
+         * can be passed directly to the compiler.
+         * @param sources the sources
+         * @return this task object
+         */
+        public JavacTask sources(String... sources) {
+            fileObjects = Stream.of(sources)
+                    .map(s -> new JavaSource(s))
+                    .collect(Collectors.toList());
+            return this;
+        }
+
+        /**
+         * Sets the file manager to be used by this task.
+         * @param fileManager the file manager
+         * @return this task object
+         */
+        public JavacTask fileManager(JavaFileManager fileManager) {
+            this.fileManager = fileManager;
+            return this;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return the name "javac"
+         */
+        @Override
+        public String name() {
+            return "javac";
+        }
+
+        /**
+         * Calls the compiler with the arguments as currently configured.
+         * @return a Result object indicating the outcome of the compilation
+         * and the content of any output written to stdout, stderr, or the
+         * main stream by the compiler.
+         * @throws TaskError if the outcome of the task is not as expected.
+         */
+        @Override
+        public Result run() {
+            if (mode == Mode.EXEC)
+                return runExec();
+
+            WriterOutput direct = new WriterOutput();
+            // The following are to catch output to System.out and System.err,
+            // in case these are used instead of the primary (main) stream
+            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
+            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
+            int rc;
+            Map<OutputKind, String> outputMap = new HashMap<>();
+            try {
+                switch (mode == null ? Mode.API : mode) {
+                    case API:
+                        rc = runAPI(direct.pw);
+                        break;
+                    case CMDLINE:
+                        rc = runCommand(direct.pw);
+                        break;
+                    default:
+                        throw new IllegalStateException();
+                }
+            } catch (IOException e) {
+                out.println("Exception occurred: " + e);
+                rc = 99;
+            } finally {
+                outputMap.put(OutputKind.STDOUT, sysOut.close());
+                outputMap.put(OutputKind.STDERR, sysErr.close());
+                outputMap.put(OutputKind.DIRECT, direct.close());
+            }
+            return checkExit(new Result(this, rc, outputMap));
+        }
+
+        private int runAPI(PrintWriter pw) throws IOException {
+//            if (compiler == null) {
+                // TODO: allow this to be set externally
+//                compiler = ToolProvider.getSystemJavaCompiler();
+                compiler = JavacTool.create();
+//            }
+
+            if (fileManager == null)
+                fileManager = compiler.getStandardFileManager(null, null, null);
+            if (outdir != null)
+                setLocation(StandardLocation.CLASS_OUTPUT, toFiles(outdir));
+            if (classpath != null)
+                setLocation(StandardLocation.CLASS_PATH, toFiles(classpath));
+            if (sourcepath != null)
+                setLocation(StandardLocation.SOURCE_PATH, toFiles(sourcepath));
+            List<String> allOpts = new ArrayList<>();
+            if (options != null)
+                allOpts.addAll(options);
+
+            Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
+            JavaCompiler.CompilationTask task = compiler.getTask(pw,
+                    fileManager,
+                    null,  // diagnostic listener; should optionally collect diags
+                    allOpts,
+                    classes,
+                    allFiles);
+            return ((JavacTaskImpl) task).doCall().exitCode;
+        }
+
+        private void setLocation(StandardLocation location, List<File> files) throws IOException {
+            if (!(fileManager instanceof StandardJavaFileManager))
+                throw new IllegalStateException("not a StandardJavaFileManager");
+            ((StandardJavaFileManager) fileManager).setLocation(location, files);
+        }
+
+        private int runCommand(PrintWriter pw) {
+            List<String> args = getAllArgs();
+            String[] argsArray = args.toArray(new String[args.size()]);
+            return com.sun.tools.javac.Main.compile(argsArray, pw);
+        }
+
+        private Result runExec() {
+            List<String> args = new ArrayList<>();
+            Path javac = getJDKTool("javac");
+            args.add(javac.toString());
+            if (includeStandardOptions) {
+                args.addAll(split(System.getProperty("test.tool.vm.opts"), " +"));
+                args.addAll(split(System.getProperty("test.compiler.opts"), " +"));
+            }
+            args.addAll(getAllArgs());
+
+            String[] argsArray = args.toArray(new String[args.size()]);
+            ProcessBuilder pb = getProcessBuilder();
+            pb.command(argsArray);
+            try {
+                return runProcess(ToolBox.this, this, pb.start());
+            } catch (IOException | InterruptedException e) {
+                throw new Error(e);
+            }
+        }
+
+        private List<String> getAllArgs() {
+            List<String> args = new ArrayList<>();
+            if (options != null)
+                args.addAll(options);
+            if (outdir != null) {
+                args.add("-d");
+                args.add(outdir);
+            }
+            if (classpath != null) {
+                args.add("-classpath");
+                args.add(classpath);
+            }
+            if (sourcepath != null) {
+                args.add("-sourcepath");
+                args.add(sourcepath);
+            }
+            if (classes != null)
+                args.addAll(classes);
+            if (files != null)
+                args.addAll(files);
+
+            return args;
+        }
+
+        private List<File> toFiles(String path) {
+            List<File> result = new ArrayList<>();
+            for (String s: path.split(File.pathSeparator)) {
+                if (!s.isEmpty())
+                    result.add(new File(s));
+            }
+            return result;
+        }
+
+        private Iterable<? extends JavaFileObject> joinFiles(
+                List<String> files, List<JavaFileObject> fileObjects) {
+            if (files == null)
+                return fileObjects;
+            if (standardJavaFileManager == null)
+                standardJavaFileManager = compiler.getStandardFileManager(null, null, null);
+            Iterable<? extends JavaFileObject> filesAsFileObjects =
+                    standardJavaFileManager.getJavaFileObjectsFromStrings(files);
+            if (fileObjects == null)
+                return filesAsFileObjects;
+            List<JavaFileObject> combinedList = new ArrayList<>();
+            for (JavaFileObject o: filesAsFileObjects)
+                combinedList.add(o);
+            combinedList.addAll(fileObjects);
+            return combinedList;
+        }
+    }
+
+    /**
+     * A task to configure and run the native header tool, javah.
+     */
+    public class JavahTask extends AbstractTask<JavahTask> {
+        private String classpath;
+        private List<String> options;
+        private List<String> classes;
+
+        /**
+         * Create a task to execute {@code javah} using {@code CMDLINE} mode.
+         */
+        public JavahTask() {
+            super(Mode.CMDLINE);
+        }
+
+        /**
+         * Sets the classpath.
+         * @param classpath the classpath
+         * @return this task object
+         */
+        public JavahTask classpath(String classpath) {
+            this.classpath = classpath;
+            return this;
+        }
+
+        /**
+         * Sets the options.
+         * @param options the options
+         * @return this task object
+         */
+        public JavahTask options(String... options) {
+            this.options = Arrays.asList(options);
+            return this;
+        }
+
+        /**
+         * Sets the classes to be analyzed.
+         * @param classes the classes
+         * @return this task object
+         */
+        public JavahTask classes(String... classes) {
+            this.classes = Arrays.asList(classes);
+            return this;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return the name "javah"
+         */
+        @Override
+        public String name() {
+            return "javah";
+        }
+
+        /**
+         * Calls the javah tool with the arguments as currently configured.
+         * @return a Result object indicating the outcome of the task
+         * and the content of any output written to stdout, stderr, or the
+         * main stream provided to the task.
+         * @throws TaskError if the outcome of the task is not as expected.
+         */
+        @Override
+        public Result run() {
+            List<String> args = new ArrayList<>();
+            if (options != null)
+                args.addAll(options);
+            if (classpath != null) {
+                args.add("-classpath");
+                args.add(classpath);
+            }
+            if (classes != null)
+                args.addAll(classes);
+
+            WriterOutput direct = new WriterOutput();
+            // These are to catch output to System.out and System.err,
+            // in case these are used instead of the primary streams
+            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
+            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
+            int rc;
+            Map<OutputKind, String> outputMap = new HashMap<>();
+            try {
+                rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), direct.pw);
+            } finally {
+                outputMap.put(OutputKind.STDOUT, sysOut.close());
+                outputMap.put(OutputKind.STDERR, sysErr.close());
+                outputMap.put(OutputKind.DIRECT, direct.close());
+            }
+            return checkExit(new Result(this, rc, outputMap));
+        }
+    }
+
+    /**
+     * A task to configure and run the disassembler tool, javap.
+     */
+    public class JavapTask extends AbstractTask<JavapTask> {
+        private String classpath;
+        private List<String> options;
+        private List<String> classes;
+
+        /**
+         * Create a task to execute {@code javap} using {@code CMDLINE} mode.
+         */
+        public JavapTask() {
+            super(Mode.CMDLINE);
+        }
+
+        /**
+         * Sets the classpath.
+         * @param classpath the classpath
+         * @return this task object
+         */
+        public JavapTask classpath(String classpath) {
+            this.classpath = classpath;
+            return this;
+        }
+
+        /**
+         * Sets the options.
+         * @param options the options
+         * @return this task object
+         */
+        public JavapTask options(String... options) {
+            this.options = Arrays.asList(options);
+            return this;
+        }
+
+        /**
+         * Sets the classes to be analyzed.
+         * @param classes the classes
+         * @return this task object
+         */
+        public JavapTask classes(String... classes) {
+            this.classes = Arrays.asList(classes);
+            return this;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return the name "javap"
+         */
+        @Override
+        public String name() {
+            return "javap";
+        }
+
+        /**
+         * Calls the javap tool with the arguments as currently configured.
+         * @return a Result object indicating the outcome of the task
+         * and the content of any output written to stdout, stderr, or the
+         * main stream.
+         * @throws TaskError if the outcome of the task is not as expected.
+         */
+        @Override
+        public Result run() {
+            List<String> args = new ArrayList<>();
+            if (options != null)
+                args.addAll(options);
+            if (classpath != null) {
+                args.add("-classpath");
+                args.add(classpath);
+            }
+            if (classes != null)
+                args.addAll(classes);
+
+            WriterOutput direct = new WriterOutput();
+            // These are to catch output to System.out and System.err,
+            // in case these are used instead of the primary streams
+            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
+            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
+
+            int rc;
+            Map<OutputKind, String> outputMap = new HashMap<>();
+            try {
+                rc = com.sun.tools.javap.Main.run(args.toArray(new String[args.size()]), direct.pw);
+            } finally {
+                outputMap.put(OutputKind.STDOUT, sysOut.close());
+                outputMap.put(OutputKind.STDERR, sysErr.close());
+                outputMap.put(OutputKind.DIRECT, direct.close());
+            }
+            return checkExit(new Result(this, rc, outputMap));
+        }
+    }
+
+    /**
+     * A task to configure and run the jar file utility.
+     */
+    public class JarTask extends AbstractTask<JarTask> {
+        private Path jar;
+        private Manifest manifest;
+        private String classpath;
+        private String mainClass;
+        private Path baseDir;
+        private List<Path> paths;
+
+        /**
+         * Creates a task to write jar files, using API mode.
+         */
+        public JarTask() {
+            super(Mode.API);
+            paths = Collections.emptyList();
+        }
+
+        /**
+         * Creates a JarTask for use with a given jar file.
+         * @param path the file
+         */
+        public JarTask(String path) {
+            this();
+            jar = Paths.get(path);
+        }
+
+        /**
+         * Sets a manifest for the jar file.
+         * @param manifest the manifest
+         * @return this task object
+         */
+        public JarTask manifest(Manifest manifest) {
+            this.manifest = manifest;
+            return this;
+        }
+
+        /**
+         * Sets a manifest for the jar file.
+         * @param manifest a string containing the contents of the manifest
+         * @return this task object
+         * @throws IOException if there is a problem creating the manifest
+         */
+        public JarTask manifest(String manifest) throws IOException {
+            this.manifest = new Manifest(new ByteArrayInputStream(manifest.getBytes()));
+            return this;
+        }
+
+        /**
+         * Sets the classpath to be written to the {@code Class-Path}
+         * entry in the manifest.
+         * @param classpath the classpath
+         * @return this task object
+         */
+        public JarTask classpath(String classpath) {
+            this.classpath = classpath;
+            return this;
+        }
+
+        /**
+         * Sets the class to be written to the {@code Main-Class}
+         * entry in the manifest..
+         * @param mainClass the name of the main class
+         * @return this task object
+         */
+        public JarTask mainClass(String mainClass) {
+            this.mainClass = mainClass;
+            return this;
+        }
+
+        /**
+         * Sets the base directory for files to be written into the jar file.
+         * @param baseDir the base directory
+         * @return this task object
+         */
+        public JarTask baseDir(String baseDir) {
+            this.baseDir = Paths.get(baseDir);
+            return this;
+        }
+
+        /**
+         * Sets the files to be written into the jar file.
+         * @param files the files
+         * @return this task object
+         */
+        public JarTask files(String... files) {
+            this.paths = Stream.of(files)
+                    .map(file -> Paths.get(file))
+                    .collect(Collectors.toList());
+            return this;
+        }
+
+        /**
+         * Provides limited jar command-like functionality.
+         * The supported commands are:
+         * <ul>
+         * <li> jar cf jarfile -C dir files...
+         * <li> jar cfm jarfile manifestfile -C dir files...
+         * </ul>
+         * Any values specified by other configuration methods will be ignored.
+         * @param args arguments in the style of those for the jar command
+         * @return a Result object containing the results of running the task
+         */
+        public Result run(String... args) {
+            if (args.length < 2)
+                throw new IllegalArgumentException();
+
+            ListIterator<String> iter = Arrays.asList(args).listIterator();
+            String first = iter.next();
+            switch (first) {
+                case "cf":
+                    jar = Paths.get(iter.next());
+                    break;
+                case "cfm":
+                    jar = Paths.get(iter.next());
+                    try (InputStream in = Files.newInputStream(Paths.get(iter.next()))) {
+                        manifest = new Manifest(in);
+                    } catch (IOException e) {
+                        throw new IOError(e);
+                    }
+                    break;
+            }
+
+            if (iter.hasNext()) {
+                if (iter.next().equals("-C"))
+                    baseDir = Paths.get(iter.next());
+                else
+                    iter.previous();
+            }
+
+            paths = new ArrayList<>();
+            while (iter.hasNext())
+                paths.add(Paths.get(iter.next()));
+
+            return run();
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return the name "jar"
+         */
+        @Override
+        public String name() {
+            return "jar";
+        }
+
+        /**
+         * Creates a jar file with the arguments as currently configured.
+         * @return a Result object indicating the outcome of the compilation
+         * and the content of any output written to stdout, stderr, or the
+         * main stream by the compiler.
+         * @throws TaskError if the outcome of the task is not as expected.
+         */
+        @Override
+        public Result run() {
+            Manifest m = (manifest == null) ? new Manifest() : manifest;
+            Attributes mainAttrs = m.getMainAttributes();
+            if (mainClass != null)
+                mainAttrs.put(Attributes.Name.MAIN_CLASS, mainClass);
+            if (classpath != null)
+                mainAttrs.put(Attributes.Name.CLASS_PATH, classpath);
+
+            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
+            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
+
+            int rc;
+            Map<OutputKind, String> outputMap = new HashMap<>();
+
+            try (OutputStream os = Files.newOutputStream(jar);
+                    JarOutputStream jos = openJar(os, m)) {
+                Path base = (baseDir == null) ? currDir : baseDir;
+                for (Path path: paths) {
+                    Files.walkFileTree(base.resolve(path), new SimpleFileVisitor<Path>() {
+                        @Override
+                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                            try {
+                                JarEntry e = new JarEntry(base.relativize(file).toString());
+                                jos.putNextEntry(e);
+                                jos.write(Files.readAllBytes(file));
+                                jos.closeEntry();
+                                return FileVisitResult.CONTINUE;
+                            } catch (IOException e) {
+                                System.err.println("Error adding " + file + " to jar file: " + e);
+                                return FileVisitResult.TERMINATE;
+                            }
+                        }
+                    });
+                }
+                rc = 0;
+            } catch (IOException e) {
+                System.err.println("Error opening " + jar + ": " + e);
+                rc = 1;
+            } finally {
+                outputMap.put(OutputKind.STDOUT, sysOut.close());
+                outputMap.put(OutputKind.STDERR, sysErr.close());
+            }
+            return checkExit(new Result(this, rc, outputMap));
+        }
+
+        private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException {
+            if (m == null || m.getMainAttributes().isEmpty() && m.getEntries().isEmpty()) {
+                return new JarOutputStream(os);
+            } else {
+                if (m.getMainAttributes().get(Attributes.Name.MANIFEST_VERSION) == null)
+                    m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
+                return new JarOutputStream(os, m);
+            }
+        }
+
+    }
+
+    /**
+     * A task to configure and run the Java launcher.
+     */
+    public class JavaTask extends AbstractTask<JavaTask> {
+        boolean includeStandardOptions = true;
+        private String classpath;
+        private List<String> vmOptions;
+        private String className;
+        private List<String> classArgs;
+
+        /**
+         * Create a task to run the Java launcher, using {@code EXEC} mode.
+         */
+        public JavaTask() {
+            super(Mode.EXEC);
+        }
+
+        /**
+         * Sets the classpath.
+         * @param classpath the classpath
+         * @return this task object
+         */
+        public JavaTask classpath(String classpath) {
+            this.classpath = classpath;
+            return this;
+        }
+
+        /**
+         * Sets the VM options.
+         * @param vmOptions the options
+         * @return this task object
+         */
+        public JavaTask vmOptions(String... vmOptions) {
+            this.vmOptions = Arrays.asList(vmOptions);
+            return this;
+        }
+
+        /**
+         * Sets the name of the class to be executed.
+         * @param className the name of the class
+         * @return this task object
+         */
+        public JavaTask className(String className) {
+            this.className = className;
+            return this;
+        }
+
+        /**
+         * Sets the arguments for the class to be executed.
+         * @param classArgs the arguments
+         * @return this task object
+         */
+        public JavaTask classArgs(String... classArgs) {
+            this.classArgs = Arrays.asList(classArgs);
+            return this;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return the name "java"
+         */
+        @Override
+        public String name() {
+            return "java";
+        }
+
+        /**
+         * Calls the Java launcher with the arguments as currently configured.
+         * @return a Result object indicating the outcome of the task
+         * and the content of any output written to stdout or stderr.
+         * @throws TaskError if the outcome of the task is not as expected.
+         */
+        @Override
+        public Result run() {
+            List<String> args = new ArrayList<>();
+            args.add(getJDKTool("java").toString());
+            if (includeStandardOptions) {
+                args.addAll(split(System.getProperty("test.vm.opts"), " +"));
+                args.addAll(split(System.getProperty("test.java.opts"), " +"));
+            }
+            if (classpath != null) {
+                args.add("-classpath");
+                args.add(classpath);
+            }
+            if (vmOptions != null)
+                args.addAll(vmOptions);
+            if (className != null)
+                args.add(className);
+            if (classArgs != null)
+                args.addAll(classArgs);
+            ProcessBuilder pb = getProcessBuilder();
+            pb.command(args);
+            try {
+                return runProcess(ToolBox.this, this, pb.start());
+            } catch (IOException | InterruptedException e) {
+                throw new Error(e);
+            }
+        }
+    }
+
+    /**
+     * A task to configure and run a general command.
+     */
+    public class ExecTask extends AbstractTask<ExecTask> {
+        private final String command;
+        private List<String> args;
+
+        /**
+         * Create a task to execute a given command, to be run using {@code EXEC} mode.
+         * @param command the command to be executed
+         */
+        public ExecTask(String command) {
+            super(Mode.EXEC);
+            this.command = command;
+        }
+
+        /**
+         * Create a task to execute a given command, to be run using {@code EXEC} mode.
+         * @param command the command to be executed
+         */
+        public ExecTask(Path command) {
+            super(Mode.EXEC);
+            this.command = command.toString();
+        }
+
+        /**
+         * Sets the arguments for the command to be executed
+         * @param args the arguments
+         * @return this task object
+         */
+        public ExecTask args(String... args) {
+            this.args = Arrays.asList(args);
+            return this;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return the name "exec"
+         */
+        @Override
+        public String name() {
+            return "exec";
+        }
+
+        /**
+         * Calls the command with the arguments as currently configured.
+         * @return a Result object indicating the outcome of the task
+         * and the content of any output written to stdout or stderr.
+         * @throws TaskError if the outcome of the task is not as expected.
+         */
+        @Override
+        public Result run() {
+            List<String> cmdArgs = new ArrayList<>();
+            cmdArgs.add(command);
+            if (args != null)
+                cmdArgs.addAll(args);
+            ProcessBuilder pb = getProcessBuilder();
+            pb.command(cmdArgs);
+            try {
+                return runProcess(ToolBox.this, this, pb.start());
+            } catch (IOException | InterruptedException e) {
+                throw new Error(e);
+            }
+        }
+    }
+
+    /**
+     * An in-memory Java source file.
+     * It is able to extract the file name from simple source text using
+     * regular expressions.
+     */
+    public static class JavaSource extends SimpleJavaFileObject {
+        private final String source;
+
+        /**
+         * Creates a in-memory file object for Java source code.
+         * @param className the name of the class
+         * @param source the source text
+         */
+        public JavaSource(String className, String source) {
+            super(URI.create(className), JavaFileObject.Kind.SOURCE);
+            this.source = source;
+        }
+
+        /**
+         * Creates a in-memory file object for Java source code.
+         * The name of the class will be inferred from the source code.
+         * @param source the source text
+         */
+        public JavaSource(String source) {
+            super(URI.create(getJavaFileNameFromSource(source)),
+                    JavaFileObject.Kind.SOURCE);
+            this.source = source;
+        }
+
+        /**
+         * Writes the source code to a file in the current directory.
+         * @throws IOException if there is a problem writing the file
+         */
+        public void write() throws IOException {
+            write(currDir);
+        }
+
+        /**
+         * Writes the source code to a file in a specified directory.
+         * @param dir the directory
+         * @throws IOException if there is a problem writing the file
+         */
+        public void write(Path dir) throws IOException {
+            Path file = dir.resolve(getJavaFileNameFromSource(source));
+            Files.createDirectories(file.getParent());
+            try (BufferedWriter out = Files.newBufferedWriter(file)) {
+                out.write(source.replace("\n", lineSeparator));
+            }
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return source;
+        }
+
+        private static Pattern packagePattern =
+                Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))");
+        private static Pattern classPattern =
+                Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)");
+
+        /**
+         * Extracts the Java file name from the class declaration.
+         * This method is intended for simple files and uses regular expressions,
+         * so comments matching the pattern can make the method fail.
+         */
+        static String getJavaFileNameFromSource(String source) {
+            String packageName = null;
+
+            Matcher matcher = packagePattern.matcher(source);
+            if (matcher.find())
+                packageName = matcher.group(1).replace(".", "/");
+
+            matcher = classPattern.matcher(source);
+            if (matcher.find()) {
+                String className = matcher.group(1) + ".java";
+                return (packageName == null) ? className : packageName + "/" + className;
+            } else {
+                throw new Error("Could not extract the java class " +
+                        "name from the provided source");
+            }
+        }
+    }
+
+    /**
+     * Extracts the Java file name from the class declaration.
+     * This method is intended for simple files and uses regular expressions,
+     * so comments matching the pattern can make the method fail.
+     * @deprecated This is a legacy method for compatibility with ToolBox v1.
+     *      Use {@link JavaSource#getName JavaSource.getName} instead.
+     * @param source the source text
+     * @return the Java file name inferred from the source
+     */
+    @Deprecated
+    public static String getJavaFileNameFromSource(String source) {
+        return JavaSource.getJavaFileNameFromSource(source);
+    }
+
+    /**
+     * A memory file manager, for saving generated files in memory.
+     * The file manager delegates to a separate file manager for listing and
+     * reading input files.
+     */
+    public static class MemoryFileManager extends ForwardingJavaFileManager {
+        private interface Content {
+            byte[] getBytes();
+            String getString();
+        }
+
+        /**
+         * Maps binary class names to generated content.
+         */
+        final Map<Location, Map<String, Content>> files;
+
+        /**
+         * Construct a memory file manager which stores output files in memory,
+         * and delegates to a default file manager for input files.
+         */
+        public MemoryFileManager() {
+            this(JavacTool.create().getStandardFileManager(null, null, null));
+        }
+
+        /**
+         * Construct a memory file manager which stores output files in memory,
+         * and delegates to a specified file manager for input files.
+         * @param fileManager the file manager to be used for input files
+         */
+        public MemoryFileManager(JavaFileManager fileManager) {
+            super(fileManager);
+            files = new HashMap<>();
+        }
+
+        @Override
+        public JavaFileObject getJavaFileForOutput(Location location,
+                                                   String name,
+                                                   JavaFileObject.Kind kind,
+                                                   FileObject sibling)
+        {
+            return new MemoryFileObject(location, name, kind);
+        }
+
+        /**
+         * Returns the content written to a file in a given location,
+         * or null if no such file has been written.
+         * @param location the location
+         * @param name the name of the file
+         * @return the content as an array of bytes
+         */
+        public byte[] getFileBytes(Location location, String name) {
+            Content content = getFile(location, name);
+            return (content == null) ? null : content.getBytes();
+        }
+
+        /**
+         * Returns the content written to a file in a given location,
+         * or null if no such file has been written.
+         * @param location the location
+         * @param name the name of the file
+         * @return the content as a string
+         */
+        public String getFileString(Location location, String name) {
+            Content content = getFile(location, name);
+            return (content == null) ? null : content.getString();
+        }
+
+        private Content getFile(Location location, String name) {
+            Map<String, Content> filesForLocation = files.get(location);
+            return (filesForLocation == null) ? null : filesForLocation.get(name);
+        }
+
+        private void save(Location location, String name, Content content) {
+            Map<String, Content> filesForLocation = files.get(location);
+            if (filesForLocation == null)
+                files.put(location, filesForLocation = new HashMap<>());
+            filesForLocation.put(name, content);
+        }
+
+        /**
+         * A writable file object stored in memory.
+         */
+        private class MemoryFileObject extends SimpleJavaFileObject {
+            private final Location location;
+            private final String name;
+
+            /**
+             * Constructs a memory file object.
+             * @param name binary name of the class to be stored in this file object
+             */
+            MemoryFileObject(Location location, String name, JavaFileObject.Kind kind) {
+                super(URI.create("mfm:///" + name.replace('.','/') + kind.extension),
+                      Kind.CLASS);
+                this.location = location;
+                this.name = name;
+            }
+
+            @Override
+            public OutputStream openOutputStream() {
+                return new FilterOutputStream(new ByteArrayOutputStream()) {
+                    @Override
+                    public void close() throws IOException {
+                        out.close();
+                        byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
+                        save(location, name, new Content() {
+                            @Override
+                            public byte[] getBytes() {
+                                return bytes;
+                            }
+                            @Override
+                            public String getString() {
+                                return new String(bytes);
+                            }
+
+                        });
+                    }
+                };
+            }
+
+            @Override
+            public Writer openWriter() {
+                return new FilterWriter(new StringWriter()) {
+                    @Override
+                    public void close() throws IOException {
+                        out.close();
+                        String text = ((StringWriter) out).toString();
+                        save(location, name, new Content() {
+                            @Override
+                            public byte[] getBytes() {
+                                return text.getBytes();
+                            }
+                            @Override
+                            public String getString() {
+                                return text;
+                            }
+
+                        });
+                    }
+                };
+            }
+        }
+
+    }
+
+}