changeset 51977:a8862960c19f

8211171: move JarUtils to top-level testlibrary Reviewed-by: alanb
author iignatyev
date Mon, 01 Oct 2018 14:54:46 -0700
parents 390f529f4f22
children 4756af2308a1
files test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java test/jaxp/javax/xml/jaxp/libs/jaxp/library/JarUtils.java test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java test/jdk/java/io/FilePermission/ReadFileOnPath.java test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java test/jdk/java/io/Serializable/resolveClass/consTest/SetupJar.java test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java test/jdk/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java test/jdk/java/lang/ClassLoader/getResource/automaticmodules/Driver.java test/jdk/java/lang/ClassLoader/securityManager/ClassLoaderTest.java test/jdk/java/lang/Package/IsCompatibleWithDriver.java test/jdk/java/lang/Package/PackageFromManifest.java test/jdk/java/lang/instrument/executableJAR/ExecJarWithAgent.java test/jdk/java/lang/module/AutomaticModulesTest.java test/jdk/java/lang/module/ModuleReader/ModuleReaderTest.java test/jdk/java/lang/module/MultiReleaseJarTest.java test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java test/jdk/java/net/URLClassLoader/closetest/CloseTest.java test/jdk/java/net/URLClassLoader/closetest/GetResourceAsStream.java test/jdk/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java test/jdk/java/nio/channels/AsynchronousChannelGroup/SetupJar.java test/jdk/java/nio/charset/spi/CharsetProviderBasicTest.java test/jdk/java/nio/charset/spi/SetupJar.java test/jdk/java/rmi/module/ModuleTest.java test/jdk/java/security/Provider/SecurityProviderModularTest.java test/jdk/java/util/ServiceLoader/ModulesTest.java test/jdk/java/util/ServiceLoader/basic/ServiceLoaderBasicTest.java test/jdk/javax/security/auth/login/modules/JaasModularClientTest.java test/jdk/javax/security/auth/login/modules/JaasModularDefaultHandlerTest.java test/jdk/jdk/modules/scenarios/automaticmodules/RunWithAutomaticModules.java test/jdk/lib/testlibrary/JarUtils.java test/jdk/sun/net/www/protocol/jar/jarbug/TestDriver.java test/jdk/tools/jlink/basic/BasicTest.java test/jdk/tools/launcher/modules/addexports/manifest/AddExportsAndOpensInManifest.java test/jdk/tools/launcher/modules/addreads/AddReadsTest.java test/jdk/tools/launcher/modules/illegalaccess/IllegalAccessTest.java test/jdk/tools/launcher/modules/patch/basic/PatchTest.java test/jdk/tools/launcher/modules/patch/basic/PatchTestWarningError.java test/jdk/tools/launcher/modules/validate/ValidateModulesTest.java test/lib/jdk/test/lib/util/JarUtils.java
diffstat 42 files changed, 300 insertions(+), 416 deletions(-) [+]
line wrap: on
line diff
--- a/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/hotspot/jtreg/runtime/Dictionary/ProtectionDomainCacheTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -26,9 +26,9 @@
  * @bug 8151486
  * @summary Call Class.forName() on the system classloader from a class loaded
  *          from a custom classloader, using the current class's protection domain.
- * @library /test/jdk/lib/testlibrary
  * @library /test/lib
- * @build jdk.test.lib.Utils JarUtils
+ * @build jdk.test.lib.Utils
+ *        jdk.test.lib.util.JarUtils
  * @build ClassForName ProtectionDomainCacheTest
  * @run main/othervm/policy=test.policy -XX:+UnlockDiagnosticVMOptions -XX:VerifySubSet=dictionary -XX:+VerifyAfterGC -Xlog:gc+verify=debug,protectiondomain=trace,class+unload:gc.log -Djava.security.manager ProtectionDomainCacheTest
  */
@@ -41,6 +41,7 @@
 import java.nio.file.Paths;
 import java.util.List;
 import jdk.test.lib.Utils;
+import jdk.test.lib.util.JarUtils;
 
 /*
  * Create .jar, load ClassForName from .jar using a URLClassLoader
--- a/test/jaxp/javax/xml/jaxp/libs/jaxp/library/JarUtils.java	Mon Oct 01 11:54:34 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, 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.
- */
-package jaxp.library;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * This class consists exclusively of static utility methods that are useful
- * for creating and manipulating JAR files.
- */
-
-public final class JarUtils {
-    private JarUtils() { }
-
-    /**
-     * Creates a JAR file.
-     *
-     * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file)
-        throws IOException
-    {
-        // create the target directory
-        Path parent = jarfile.getParent();
-        if (parent != null)
-            Files.createDirectories(parent);
-
-        List<Path> entries = new ArrayList<>();
-        for (Path entry : file) {
-            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
-                        (p, attrs) -> attrs.isRegularFile())
-                    .map(e -> dir.relativize(e))
-                    .forEach(entries::add);
-        }
-
-        try (OutputStream out = Files.newOutputStream(jarfile);
-             JarOutputStream jos = new JarOutputStream(out))
-        {
-            if (man != null) {
-                JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
-                jos.putNextEntry(je);
-                man.write(jos);
-                jos.closeEntry();
-            }
-
-            for (Path entry : entries) {
-                String name = toJarEntryName(entry);
-                jos.putNextEntry(new JarEntry(name));
-                Files.copy(dir.resolve(entry), jos);
-                jos.closeEntry();
-            }
-        }
-    }
-
-    /**
-     * Creates a JAR file.
-     *
-     * Equivalent to {@code jar cf <jarfile>  -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void createJarFile(Path jarfile, Path dir, Path... file)
-        throws IOException
-    {
-        createJarFile(jarfile, null, dir, file);
-    }
-
-    /**
-     * Creates a JAR file.
-     *
-     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void createJarFile(Path jarfile, Path dir, String... input)
-        throws IOException
-    {
-        Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
-        createJarFile(jarfile, dir, paths);
-    }
-
-    /**
-     * Creates a JAR file from the contents of a directory.
-     *
-     * Equivalent to {@code jar cf <jarfile> -C <dir> .}
-     */
-    public static void createJarFile(Path jarfile, Path dir) throws IOException {
-        createJarFile(jarfile, dir, Paths.get("."));
-    }
-
-    /**
-     * Map a file path to the equivalent name in a JAR file
-     */
-    private static String toJarEntryName(Path file) {
-        Path normalized = file.normalize();
-        return normalized.subpath(0, normalized.getNameCount())  // drop root
-                .toString()
-                .replace(File.separatorChar, '/');
-    }
-}
--- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -42,9 +42,11 @@
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogManager;
 import javax.xml.catalog.CatalogResolver;
+
 import static jaxp.library.JAXPTestUtilities.getSystemProperty;
-import jaxp.library.JarUtils;
 import jaxp.library.SimpleHttpServer;
+import jdk.test.lib.util.JarUtils;
+
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
@@ -56,10 +58,10 @@
 /*
  * @test
  * @bug 8151154 8171243
- * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest /test/lib
  * @run testng/othervm catalog.CatalogFileInputTest
  * @summary Verifies that the Catalog API accepts valid URIs only;
-            Verifies that the CatalogFeatures' builder throws
+ *          Verifies that the CatalogFeatures' builder throws
  *          IllegalArgumentException on invalid file inputs.
  *          This test was splitted from CatalogTest.java due to
  *          JDK-8168968, it has to only run without SecurityManager
--- a/test/jdk/java/io/FilePermission/ReadFileOnPath.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/io/FilePermission/ReadFileOnPath.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 8164705
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          jdk.compiler
  * @build jdk.test.lib.compiler.CompilerUtils
@@ -34,12 +34,14 @@
  *        jdk.test.lib.JDKToolLauncher
  *        jdk.test.lib.Platform
  *        jdk.test.lib.process.*
+ *        jdk.test.lib.util.JarUtils
  * @run main ReadFileOnPath
  * @summary Still able to read file on the same path
  */
 
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 
 import java.nio.file.Files;
 import java.nio.file.Path;
--- a/test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,8 +24,8 @@
 /*
  * @test
  * @bug 4765255
- * @library /lib/testlibrary
- * @build JarUtils A B C D PackageAccessTest
+ * @library /test/lib
+ * @build jdk.test.lib.util.JarUtils A B C D PackageAccessTest
  * @run main PackageAccessTest
  * @summary Verify proper functioning of package equality checks used to
  *          determine accessibility of superclass constructor and inherited
@@ -46,6 +46,8 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
+import jdk.test.lib.util.JarUtils;
+
 public class PackageAccessTest {
 
     static Class bcl;
--- a/test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,8 +24,8 @@
 /*
  * @test
  * @bug 4413434
- * @library /lib/testlibrary
- * @build JarUtils SetupJar Boot
+ * @library /test/lib
+ * @build jdk.test.lib.util.JarUtils SetupJar Boot
  * @run driver SetupJar
  * @run main/othervm -Xbootclasspath/a:boot.jar ConsTest
  * @summary Verify that generated java.lang.reflect implementation classes do
@@ -39,6 +39,8 @@
 import java.io.Serializable;
 import java.lang.reflect.Constructor;
 
+import jdk.test.lib.util.JarUtils;
+
 public class ConsTest implements Serializable {
     public static void main(String[] args) throws Exception {
         Constructor cons = Boot.class.getConstructor(
--- a/test/jdk/java/io/Serializable/resolveClass/consTest/SetupJar.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/io/Serializable/resolveClass/consTest/SetupJar.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,6 +24,8 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
+import jdk.test.lib.util.JarUtils;
+
 public class SetupJar {
 
     public static void main(String args[]) throws Exception {
--- a/test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,8 +24,8 @@
 /*
  * @test
  * @bug 4413434
- * @library /lib/testlibrary
- * @build JarUtils Foo
+ * @library /test/lib
+ * @build jdk.test.lib.util.JarUtils Foo
  * @run main DeserializeButtonTest
  * @summary Verify that class loaded outside of application class loader is
  *          correctly resolved during deserialization when read in by custom
@@ -38,6 +38,8 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
+import jdk.test.lib.util.JarUtils;
+
 public class DeserializeButtonTest {
     public static void main(String[] args) throws Exception {
         setup();
--- a/test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,8 +24,8 @@
 /*
  * @test
  * @bug 4325590
- * @library /lib/testlibrary
- * @build JarUtils A B
+ * @library /test/lib
+ * @build jdk.test.lib.util.JarUtils A B
  * @run main SuperclassDataLossTest
  * @summary Verify that superclass data is not lost when incoming superclass
  *          descriptor is matched with local class that is not a superclass of
@@ -47,6 +47,8 @@
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
 
+import jdk.test.lib.util.JarUtils;
+
 class MixedSuperclassStream extends ObjectInputStream {
     private boolean ldr12A;
     private URLClassLoader ldr1;
--- a/test/jdk/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java	Mon Oct 01 14:54:46 2018 -0700
@@ -26,9 +26,9 @@
  * @bug 8151486
  * @summary Call Class.forName() on the system classloader from a class loaded
  *          from a custom classloader.
- * @library /lib/testlibrary
  * @library /test/lib
- * @build jdk.test.lib.Utils JarUtils
+ * @build jdk.test.lib.Utils
+ *        jdk.test.lib.util.JarUtils
  * @build ClassForName ClassForNameLeak
  * @run main/othervm/policy=test.policy -Djava.security.manager ClassForNameLeak
  */
@@ -49,7 +49,9 @@
 import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+
 import jdk.test.lib.Utils;
+import jdk.test.lib.util.JarUtils;
 
 /*
  * Create .jar, load ClassForName from .jar using a URLClassLoader
--- a/test/jdk/java/lang/ClassLoader/getResource/automaticmodules/Driver.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/ClassLoader/getResource/automaticmodules/Driver.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,8 +23,9 @@
 
 /**
  * @test
- * @library /lib/testlibrary /test/lib
- * @build Driver Main JarUtils
+ * @library /test/lib
+ * @build Driver Main
+ *        jdk.test.lib.util.JarUtils
  * @run main Driver
  * @summary Test ClassLoader.getResourceXXX to locate resources in an automatic
  *          module
@@ -39,6 +40,7 @@
 import java.util.jar.Manifest;
 
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 /**
  * The driver creates a JAR file containing p/Foo.class, p/foo.properties,
--- a/test/jdk/java/lang/ClassLoader/securityManager/ClassLoaderTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/ClassLoader/securityManager/ClassLoaderTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -26,10 +26,9 @@
  * @bug 8168423
  * @summary Different types of ClassLoader running with(out) SecurityManager and
  *          (in)valid security policy file.
- * @library /lib/testlibrary
  * @library /test/lib
  * @modules java.base/jdk.internal.module
- * @build JarUtils
+ * @build jdk.test.lib.util.JarUtils
  * @build TestClassLoader TestClient
  * @run main ClassLoaderTest -noPolicy
  * @run main ClassLoaderTest -validPolicy
@@ -51,6 +50,7 @@
 import java.util.List;
 import jdk.internal.module.ModuleInfoWriter;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 public class ClassLoaderTest {
 
--- a/test/jdk/java/lang/Package/IsCompatibleWithDriver.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/Package/IsCompatibleWithDriver.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,10 +25,9 @@
  * @test
  * @bug 4227825 4785473
  * @summary Test behaviour of Package.isCompatibleWith().
- * @library /lib/testlibrary
  * @library /test/lib
  * @build A IsCompatibleWith
- *        JarUtils
+ *        jdk.test.lib.util.JarUtils
  *        jdk.test.lib.process.*
  * @run main IsCompatibleWithDriver
  */
@@ -44,6 +43,7 @@
 
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.util.JarUtils;
 
 public class IsCompatibleWithDriver {
     public static void main(String args[]) throws Throwable {
--- a/test/jdk/java/lang/Package/PackageFromManifest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/Package/PackageFromManifest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -27,7 +27,6 @@
  * @summary The test will create JAR file(s) with the manifest file
  *          that customized package versioning information (different info for
  *          same package if multiple jars). Then verify package versioning info
- * @library /lib/testlibrary
  * @library /test/lib
  * @modules jdk.compiler
  * @run main PackageFromManifest setup test
@@ -42,6 +41,7 @@
 import jdk.test.lib.compiler.CompilerUtils;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.util.FileUtils;
+import jdk.test.lib.util.JarUtils;
 
 import java.io.File;
 import java.io.IOException;
--- a/test/jdk/java/lang/instrument/executableJAR/ExecJarWithAgent.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/instrument/executableJAR/ExecJarWithAgent.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,9 +23,9 @@
 
 /**
  * @test
- * @library /lib/testlibrary
  * @library /test/lib
- * @build ExecJarWithAgent Main Agent AgentHelper JarUtils jdk.testlibrary.*
+ * @build ExecJarWithAgent Main Agent AgentHelper
+ *        jdk.test.lib.util.JarUtils
  * @run testng ExecJarWithAgent
  * @summary Test starting agents in executable JAR files
  */
@@ -41,6 +41,7 @@
 
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.util.JarUtils;
 
 @Test
 public class ExecJarWithAgent {
--- a/test/jdk/java/lang/module/AutomaticModulesTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/module/AutomaticModulesTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,8 +23,9 @@
 
 /**
  * @test
- * @library /lib/testlibrary
- * @build AutomaticModulesTest ModuleUtils JarUtils
+ * @library /lib/testlibrary /test/lib
+ * @build AutomaticModulesTest ModuleUtils
+ *        jdk.test.lib.util.JarUtils
  * @run testng AutomaticModulesTest
  * @summary Basic tests for automatic modules
  */
@@ -48,6 +49,8 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import jdk.test.lib.util.JarUtils;
+
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import static org.testng.Assert.*;
--- a/test/jdk/java/lang/module/ModuleReader/ModuleReaderTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/module/ModuleReader/ModuleReaderTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,11 +23,13 @@
 
 /**
  * @test
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules java.base/jdk.internal.module
  *          jdk.compiler
  *          jdk.jlink
- * @build ModuleReaderTest jdk.test.lib.compiler.CompilerUtils JarUtils
+ * @build ModuleReaderTest
+ *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  * @run testng ModuleReaderTest
  * @summary Basic tests for java.lang.module.ModuleReader
  */
@@ -55,6 +57,7 @@
 
 import jdk.internal.module.ModulePath;
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
--- a/test/jdk/java/lang/module/MultiReleaseJarTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/module/MultiReleaseJarTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,9 +23,9 @@
 
 /**
  * @test
- * @library /lib/testlibrary
+ * @library /test/lib
  * @modules java.base/jdk.internal.module
- * @build MultiReleaseJarTest JarUtils
+ * @build MultiReleaseJarTest jdk.test.lib.util.JarUtils
  * @run testng MultiReleaseJarTest
  * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarTest
  * @summary Basic test of modular JARs as multi-release JARs
@@ -55,6 +55,7 @@
 import java.util.jar.Manifest;
 
 import jdk.internal.module.ModuleInfoWriter;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.Test;
 import static org.testng.Assert.*;
--- a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,8 +24,9 @@
 /**
  * @test
  * @modules jdk.zipfs
- * @library /lib/testlibrary
- * @build ModulesInCustomFileSystem JarUtils m1/* m2/*
+ * @library /test/lib
+ * @build ModulesInCustomFileSystem m1/* m2/*
+ *        jdk.test.lib.util.JarUtils
  * @run testng/othervm ModulesInCustomFileSystem
  * @summary Test ModuleFinder to find modules in a custom file system
  */
@@ -43,6 +44,8 @@
 import java.nio.file.Paths;
 import java.util.Set;
 
+import jdk.test.lib.util.JarUtils;
+
 import org.testng.annotations.Test;
 import static org.testng.Assert.*;
 
--- a/test/jdk/java/net/URLClassLoader/closetest/CloseTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/net/URLClassLoader/closetest/CloseTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -28,12 +28,12 @@
  *          jdk.httpserver
  *          jdk.compiler
  * @library ../../../../com/sun/net/httpserver
- *          /lib/testlibrary
  *          /test/lib
  * @build jdk.test.lib.compiler.CompilerUtils
  *        jdk.test.lib.util.FileUtils
+ *        jdk.test.lib.util.JarUtils
  *        jdk.test.lib.Platform
- *        FileServerHandler JarUtils
+ *        FileServerHandler
  * @run main/othervm CloseTest
  * @summary URL-downloaded jar files can consume all available file descriptors
  */
@@ -49,6 +49,7 @@
 import java.nio.file.Paths;
 
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 
 import com.sun.net.httpserver.HttpContext;
 import com.sun.net.httpserver.HttpServer;
--- a/test/jdk/java/net/URLClassLoader/closetest/GetResourceAsStream.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/net/URLClassLoader/closetest/GetResourceAsStream.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,12 +24,12 @@
 /**
  * @test
  * @bug 6899919
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules jdk.compiler
  * @build jdk.test.lib.compiler.CompilerUtils
  *        jdk.test.lib.util.FileUtils
+ *        jdk.test.lib.util.JarUtils
  *        jdk.test.lib.Platform
- *        JarUtils
  * @run main/othervm GetResourceAsStream
  */
 
@@ -44,6 +44,7 @@
 import java.nio.file.StandardCopyOption;
 import java.nio.file.StandardOpenOption;
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 
 public class GetResourceAsStream extends Common {
     private static  final String WORK_DIR = System.getProperty("user.dir");
--- a/test/jdk/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,8 +25,9 @@
  * @test
  * @bug 4607272
  * @summary tests tasks can be submitted to a channel group's thread pool.
- * @library /lib/testlibrary bootlib
- * @build JarUtils PrivilegedThreadFactory Attack
+ * @library /test/lib bootlib
+ * @build PrivilegedThreadFactory Attack
+ *        jdk.test.lib.util.JarUtils
  * @run driver SetupJar
  * @run main/othervm -Xbootclasspath/a:privileged.jar AsExecutor
  */
--- a/test/jdk/java/nio/channels/AsynchronousChannelGroup/SetupJar.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/nio/channels/AsynchronousChannelGroup/SetupJar.java	Mon Oct 01 14:54:46 2018 -0700
@@ -26,6 +26,8 @@
 import java.nio.file.Paths;
 import java.util.stream.Stream;
 
+import jdk.test.lib.util.JarUtils;
+
 public class SetupJar {
     public static void main(String args[]) throws Exception {
         String cp = System.getProperty("test.class.path");
--- a/test/jdk/java/nio/charset/spi/CharsetProviderBasicTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/nio/charset/spi/CharsetProviderBasicTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -26,14 +26,13 @@
  * @bug 4429040 4591027 4814743
  * @summary Unit test for charset providers
  * @library /test/lib
- *          /lib/testlibrary
  * @build jdk.test.lib.Utils
  *        jdk.test.lib.Asserts
  *        jdk.test.lib.JDKToolFinder
  *        jdk.test.lib.JDKToolLauncher
  *        jdk.test.lib.Platform
  *        jdk.test.lib.process.*
- *        JarUtils
+ *        jdk.test.lib.util.JarUtils
  *        FooCharset FooProvider CharsetTest
  * @run driver SetupJar
  * @run testng CharsetProviderBasicTest
--- a/test/jdk/java/nio/charset/spi/SetupJar.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/nio/charset/spi/SetupJar.java	Mon Oct 01 14:54:46 2018 -0700
@@ -28,6 +28,8 @@
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.nio.file.StandardOpenOption.CREATE;
 
+import jdk.test.lib.util.JarUtils;
+
 public class SetupJar {
 
     private static final String PROVIDER
--- a/test/jdk/java/rmi/module/ModuleTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/rmi/module/ModuleTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,9 +23,11 @@
 
 /**
  * @test
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @build jdk.test.lib.process.ProcessTools
- *        ModuleTest jdk.test.lib.compiler.CompilerUtils JarUtils
+ *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
+ *        ModuleTest
  * @run testng ModuleTest
  * @summary Basic tests for using rmi in module world
  */
@@ -37,6 +39,7 @@
 import java.io.File;
 import java.nio.file.Paths;
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
--- a/test/jdk/java/security/Provider/SecurityProviderModularTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/security/Provider/SecurityProviderModularTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -40,6 +40,7 @@
 import java.lang.module.ModuleDescriptor.Builder;
 import jdk.internal.module.ModuleInfoWriter;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 
 /*
@@ -47,9 +48,9 @@
  * @bug 8130360 8183310
  * @summary Test security provider in different combination of modular option
  *          defined with(out) service description.
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules java.base/jdk.internal.module
- * @build JarUtils TestProvider TestClient
+ * @build jdk.test.lib.util.JarUtils TestProvider TestClient
  * @run main SecurityProviderModularTest CL true
  * @run main SecurityProviderModularTest CL false
  * @run main SecurityProviderModularTest SL true
--- a/test/jdk/java/util/ServiceLoader/ModulesTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/util/ServiceLoader/ModulesTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -24,9 +24,9 @@
 /**
  * @test
  * @modules java.scripting
- * @library modules /lib/testlibrary
+ * @library modules /test/lib
  * @build bananascript/*
- * @build JarUtils
+ * @build jdk.test.lib.util.JarUtils
  * @compile classpath/pearscript/org/pear/PearScriptEngineFactory.java
  *          classpath/pearscript/org/pear/PearScript.java
  * @run testng/othervm ModulesTest
@@ -53,6 +53,8 @@
 import java.util.stream.Stream;
 import javax.script.ScriptEngineFactory;
 
+import jdk.test.lib.util.JarUtils;
+
 import org.testng.annotations.Test;
 import org.testng.annotations.BeforeTest;
 import static org.testng.Assert.*;
--- a/test/jdk/java/util/ServiceLoader/basic/ServiceLoaderBasicTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/java/util/ServiceLoader/basic/ServiceLoaderBasicTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,8 +25,9 @@
  * @test
  * @bug 4640520 6354623 7198496
  * @summary Unit test for java.util.ServiceLoader
- * @library /lib/testlibrary /test/lib
- * @build JarUtils jdk.test.lib.process.*
+ * @library /test/lib
+ * @build jdk.test.lib.process.*
+ *        jdk.test.lib.util.JarUtils
  *        Basic Load FooService FooProvider1 FooProvider2 FooProvider3 BarProvider
  * @run testng ServiceLoaderBasicTest
  */
@@ -41,6 +42,7 @@
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Utils;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
--- a/test/jdk/javax/security/auth/login/modules/JaasModularClientTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/javax/security/auth/login/modules/JaasModularClientTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -37,15 +37,15 @@
 import java.util.stream.Stream;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
-
+import jdk.test.lib.util.JarUtils;
 
 /*
  * @test
  * @bug 8078813 8183310
  * @summary Test custom JAAS login module with all possible modular option.
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules java.base/jdk.internal.module
- * @build JarUtils
+ * @build jdk.test.lib.util.JarUtils
  * @build TestLoginModule JaasClient
  * @run main JaasModularClientTest false
  * @run main JaasModularClientTest true
--- a/test/jdk/javax/security/auth/login/modules/JaasModularDefaultHandlerTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/javax/security/auth/login/modules/JaasModularDefaultHandlerTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -36,14 +36,15 @@
 import java.util.stream.Stream;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.util.JarUtils;
 
 /*
  * @test
  * @bug 8151654 8183310
  * @summary Test default callback handler with all possible modular option.
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules java.base/jdk.internal.module
- * @build JarUtils
+ * @build jdk.test.lib.util.JarUtils
  * @build TestCallbackHandler TestLoginModule JaasClientWithDefaultHandler
  * @run main JaasModularDefaultHandlerTest
  */
--- a/test/jdk/jdk/modules/scenarios/automaticmodules/RunWithAutomaticModules.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/jdk/modules/scenarios/automaticmodules/RunWithAutomaticModules.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,11 +23,13 @@
 
 /**
  * @test
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules jdk.compiler
  *          java.scripting
  *          jdk.zipfs
- * @build RunWithAutomaticModules jdk.test.lib.compiler.CompilerUtils JarUtils
+ * @build RunWithAutomaticModules
+ *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  *        jdk.test.lib.process.ProcessTools
  * @run testng RunWithAutomaticModules
  * @summary Runs tests that make use of automatic modules
@@ -38,6 +40,7 @@
 import java.nio.file.Paths;
 
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 import static jdk.test.lib.process.ProcessTools.*;
 
 import org.testng.annotations.Test;
--- a/test/jdk/lib/testlibrary/JarUtils.java	Mon Oct 01 11:54:34 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 2015, 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.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * This class consists exclusively of static utility methods that are useful
- * for creating and manipulating JAR files.
- */
-
-public final class JarUtils {
-    private JarUtils() { }
-
-    /**
-     * Creates a JAR file.
-     *
-     * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file)
-        throws IOException
-    {
-        // create the target directory
-        Path parent = jarfile.getParent();
-        if (parent != null)
-            Files.createDirectories(parent);
-
-        List<Path> entries = new ArrayList<>();
-        for (Path entry : file) {
-            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
-                        (p, attrs) -> attrs.isRegularFile())
-                    .map(e -> dir.relativize(e))
-                    .forEach(entries::add);
-        }
-
-        try (OutputStream out = Files.newOutputStream(jarfile);
-             JarOutputStream jos = new JarOutputStream(out))
-        {
-            if (man != null) {
-                JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
-                jos.putNextEntry(je);
-                man.write(jos);
-                jos.closeEntry();
-            }
-
-            for (Path entry : entries) {
-                String name = toJarEntryName(entry);
-                jos.putNextEntry(new JarEntry(name));
-                Files.copy(dir.resolve(entry), jos);
-                jos.closeEntry();
-            }
-        }
-    }
-
-    /**
-     * Creates a JAR file.
-     *
-     * Equivalent to {@code jar cf <jarfile>  -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void createJarFile(Path jarfile, Path dir, Path... file)
-        throws IOException
-    {
-        createJarFile(jarfile, null, dir, file);
-    }
-
-    /**
-     * Creates a JAR file.
-     *
-     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void createJarFile(Path jarfile, Path dir, String... input)
-        throws IOException
-    {
-        Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
-        createJarFile(jarfile, dir, paths);
-    }
-
-    /**
-     * Creates a JAR file from the contents of a directory.
-     *
-     * Equivalent to {@code jar cf <jarfile> -C <dir> .}
-     */
-    public static void createJarFile(Path jarfile, Path dir) throws IOException {
-        createJarFile(jarfile, dir, Paths.get("."));
-    }
-
-    /**
-     * Update a JAR file.
-     *
-     * Equivalent to {@code jar uf <jarfile> -C <dir> file...}
-     *
-     * The input files are resolved against the given directory. Any input
-     * files that are directories are processed recursively.
-     */
-    public static void updateJarFile(Path jarfile, Path dir, Path... file)
-        throws IOException
-    {
-        List<Path> entries = new ArrayList<>();
-        for (Path entry : file) {
-            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
-                    (p, attrs) -> attrs.isRegularFile())
-                    .map(e -> dir.relativize(e))
-                    .forEach(entries::add);
-        }
-
-        Set<String> names = entries.stream()
-                .map(JarUtils::toJarEntryName)
-                .collect(Collectors.toSet());
-
-        Path tmpfile = Files.createTempFile("jar", "jar");
-
-        try (OutputStream out = Files.newOutputStream(tmpfile);
-             JarOutputStream jos = new JarOutputStream(out))
-        {
-            // copy existing entries from the original JAR file
-            try (JarFile jf = new JarFile(jarfile.toString())) {
-                Enumeration<JarEntry> jentries = jf.entries();
-                while (jentries.hasMoreElements()) {
-                    JarEntry jentry = jentries.nextElement();
-                    if (!names.contains(jentry.getName())) {
-                        jos.putNextEntry(jentry);
-                        jf.getInputStream(jentry).transferTo(jos);
-                    }
-                }
-            }
-
-            // add the new entries
-            for (Path entry : entries) {
-                String name = toJarEntryName(entry);
-                jos.putNextEntry(new JarEntry(name));
-                Files.copy(dir.resolve(entry), jos);
-            }
-        }
-
-        // replace the original JAR file
-        Files.move(tmpfile, jarfile, StandardCopyOption.REPLACE_EXISTING);
-    }
-
-    /**
-     * Update a JAR file.
-     *
-     * Equivalent to {@code jar uf <jarfile> -C <dir> .}
-     */
-    public static void updateJarFile(Path jarfile, Path dir) throws IOException {
-        updateJarFile(jarfile, dir, Paths.get("."));
-    }
-
-
-    /**
-     * Map a file path to the equivalent name in a JAR file
-     */
-    private static String toJarEntryName(Path file) {
-        Path normalized = file.normalize();
-        return normalized.subpath(0, normalized.getNameCount())  // drop root
-                .toString()
-                .replace(File.separatorChar, '/');
-    }
-}
--- a/test/jdk/sun/net/www/protocol/jar/jarbug/TestDriver.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/sun/net/www/protocol/jar/jarbug/TestDriver.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,7 +25,6 @@
  * @test
  * @bug 4361044 4388202 4418643 4523159 4730642
  * @library /test/lib
- *          /lib/testlibrary
  * @modules jdk.compiler
  * @build jdk.test.lib.compiler.CompilerUtils
  *        jdk.test.lib.Utils
@@ -34,7 +33,8 @@
  *        jdk.test.lib.JDKToolLauncher
  *        jdk.test.lib.Platform
  *        jdk.test.lib.process.*
- *        src.test.src.TestDriver JarUtils
+ *        jdk.test.lib.util.JarUtils
+ *        src.test.src.TestDriver
  * @summary various resource and classloading bugs related to jar files
  * @run main/othervm TestDriver
  */
@@ -42,6 +42,7 @@
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.compiler.CompilerUtils;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 import java.io.File;
 import java.nio.file.Files;
--- a/test/jdk/tools/jlink/basic/BasicTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/jlink/basic/BasicTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,13 +25,14 @@
  * @test
  * @summary Basic test of jlink to create jmods and images
  * @author Andrei Eremeev
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules java.base/jdk.internal.module
  *          jdk.jlink
  *          jdk.compiler
  * @build jdk.test.lib.process.ProcessTools
  *        jdk.test.lib.process.OutputAnalyzer
- *        JarUtils jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  * @run main BasicTest
  */
 
@@ -48,6 +49,7 @@
 import jdk.test.lib.compiler.CompilerUtils;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 public class BasicTest {
     static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
--- a/test/jdk/tools/launcher/modules/addexports/manifest/AddExportsAndOpensInManifest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/launcher/modules/addexports/manifest/AddExportsAndOpensInManifest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,10 +23,10 @@
 
 /**
  * @test
- * @library /lib/testlibrary
  * @library /test/lib
  * @modules jdk.compiler
- * @build AddExportsAndOpensInManifest Test2 JarUtils jdk.testlibrary.*
+ * @build AddExportsAndOpensInManifest Test2
+ *        jdk.test.lib.util.JarUtils
  * @compile --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED Test1.java
  * @run testng AddExportsAndOpensInManifest
  * @summary Basic test for Add-Exports and Add-Opens attributes in the
@@ -42,6 +42,7 @@
 
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
--- a/test/jdk/tools/launcher/modules/addreads/AddReadsTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/launcher/modules/addreads/AddReadsTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,10 +23,11 @@
 
 /**
  * @test
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules jdk.compiler
- * @build AddReadsTest JarUtils
+ * @build AddReadsTest
  *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  * @run testng AddReadsTest
  * @summary Basic tests for java --add-reads
  */
@@ -36,6 +37,7 @@
 
 import jdk.test.lib.compiler.CompilerUtils;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.util.JarUtils;
 import static jdk.test.lib.process.ProcessTools.*;
 
 import org.testng.annotations.BeforeTest;
--- a/test/jdk/tools/launcher/modules/illegalaccess/IllegalAccessTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/launcher/modules/illegalaccess/IllegalAccessTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -26,9 +26,10 @@
  * @requires vm.compMode != "Xcomp"
  * @modules java.base/jdk.internal.misc
  *          java.base/sun.security.x509
- * @library /test/lib /lib/testlibrary modules
- * @build IllegalAccessTest TryAccess JarUtils
+ * @library /test/lib modules
+ * @build IllegalAccessTest TryAccess
  *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  * @build m/*
  * @run testng/othervm/timeout=180 IllegalAccessTest
  * @summary Basic test for java --illegal-access=$VALUE
@@ -46,6 +47,7 @@
 import jdk.test.lib.compiler.CompilerUtils;
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
--- a/test/jdk/tools/launcher/modules/patch/basic/PatchTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/launcher/modules/patch/basic/PatchTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,11 +23,12 @@
 
 /**
  * @test
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules jdk.compiler
  *          jdk.naming.dns
- * @build PatchTest JarUtils
+ * @build PatchTest
  *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  * @run testng PatchTest
  * @summary Basic test for --patch-module
  */
@@ -40,6 +41,7 @@
 import java.util.stream.Stream;
 
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 import static jdk.test.lib.process.ProcessTools.*;
 
 import org.testng.annotations.BeforeTest;
--- a/test/jdk/tools/launcher/modules/patch/basic/PatchTestWarningError.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/launcher/modules/patch/basic/PatchTestWarningError.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,10 +25,11 @@
  * @test
  * @bug 8168836
  * @summary Basic argument validation for --patch-module
- * @library /lib/testlibrary /test/lib
+ * @library /test/lib
  * @modules jdk.compiler
- * @build PatchTestWarningError JarUtils
+ * @build PatchTestWarningError
  *        jdk.test.lib.compiler.CompilerUtils
+ *        jdk.test.lib.util.JarUtils
  * @run testng PatchTestWarningError
  */
 
@@ -40,6 +41,7 @@
 import java.util.stream.Stream;
 
 import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.JarUtils;
 import static jdk.test.lib.process.ProcessTools.*;
 
 import org.testng.annotations.BeforeTest;
--- a/test/jdk/tools/launcher/modules/validate/ValidateModulesTest.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/jdk/tools/launcher/modules/validate/ValidateModulesTest.java	Mon Oct 01 14:54:46 2018 -0700
@@ -25,8 +25,8 @@
  * @test
  * @bug 8178380 8194937
  * @modules java.xml
- * @library src /lib/testlibrary /test/lib
- * @build ValidateModulesTest hello/* JarUtils
+ * @library src /test/lib
+ * @build ValidateModulesTest hello/* jdk.test.lib.util.JarUtils
  * @run testng ValidateModulesTest
  * @summary Basic test for java --validate-modules
  */
@@ -38,6 +38,7 @@
 
 import jdk.test.lib.process.ProcessTools;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.util.JarUtils;
 
 import org.testng.annotations.Test;
 import static org.testng.Assert.*;
--- a/test/lib/jdk/test/lib/util/JarUtils.java	Mon Oct 01 11:54:34 2018 -0700
+++ b/test/lib/jdk/test/lib/util/JarUtils.java	Mon Oct 01 14:54:46 2018 -0700
@@ -23,31 +23,173 @@
 
 package jdk.test.lib.util;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
- * Common library for various test jar file utility functions.
+ * This class consists exclusively of static utility methods that are useful
+ * for creating and manipulating JAR files.
  */
 public final class JarUtils {
+    private JarUtils() { }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... files)
+            throws IOException
+    {
+        // create the target directory
+        Path parent = jarfile.getParent();
+        if (parent != null) {
+            Files.createDirectories(parent);
+        }
+
+        List<Path> entries = findAllRegularFiles(dir, files);
+
+        try (OutputStream out = Files.newOutputStream(jarfile);
+             JarOutputStream jos = new JarOutputStream(out)) {
+            if (man != null) {
+                JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+                jos.putNextEntry(je);
+                man.write(jos);
+                jos.closeEntry();
+            }
+
+            for (Path entry : entries) {
+                String name = toJarEntryName(entry);
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+                jos.closeEntry();
+            }
+        }
+    }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile>  -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, Path... files)
+            throws IOException
+    {
+        createJarFile(jarfile, null, dir, files);
+    }
+
+    /**
+     * Creates a JAR file from the contents of a directory.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> .}
+     */
+    public static void createJarFile(Path jarfile, Path dir) throws IOException {
+        createJarFile(jarfile, dir, Paths.get("."));
+    }
+
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, String... input)
+            throws IOException
+    {
+        Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
+        createJarFile(jarfile, dir, paths);
+    }
+
+    /**
+     * Updates a JAR file.
+     *
+     * Equivalent to {@code jar uf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void updateJarFile(Path jarfile, Path dir, Path... files)
+            throws IOException
+    {
+        List<Path> entries = findAllRegularFiles(dir, files);
+
+        Set<String> names = entries.stream()
+                                   .map(JarUtils::toJarEntryName)
+                                   .collect(Collectors.toSet());
+
+        Path tmpfile = Files.createTempFile("jar", "jar");
+
+        try (OutputStream out = Files.newOutputStream(tmpfile);
+             JarOutputStream jos = new JarOutputStream(out)) {
+            // copy existing entries from the original JAR file
+            try (JarFile jf = new JarFile(jarfile.toString())) {
+                Enumeration<JarEntry> jentries = jf.entries();
+                while (jentries.hasMoreElements()) {
+                    JarEntry jentry = jentries.nextElement();
+                    if (!names.contains(jentry.getName())) {
+                        jos.putNextEntry(jentry);
+                        jf.getInputStream(jentry).transferTo(jos);
+                    }
+                }
+            }
+
+            // add the new entries
+            for (Path entry : entries) {
+                String name = toJarEntryName(entry);
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+            }
+        }
+
+        // replace the original JAR file
+        Files.move(tmpfile, jarfile, StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    /**
+     * Updates a JAR file.
+     *
+     * Equivalent to {@code jar uf <jarfile> -C <dir> .}
+     */
+    public static void updateJarFile(Path jarfile, Path dir) throws IOException {
+        updateJarFile(jarfile, dir, Paths.get("."));
+    }
+
 
     /**
      * Create jar file with specified files. If a specified file does not exist,
      * a new jar entry will be created with the file name itself as the content.
      */
+    @Deprecated
     public static void createJar(String dest, String... files)
             throws IOException {
         try (JarOutputStream jos = new JarOutputStream(
@@ -81,6 +223,7 @@
      *              will be removed. If no "-" exists, all files belong to
      *              the 1st group.
      */
+    @Deprecated
     public static void updateJar(String src, String dest, String... files)
             throws IOException {
         Map<String,Object> changes = new HashMap<>();
@@ -118,6 +261,7 @@
      *                Existing entries in src not a key is unmodified.
      * @throws IOException
      */
+    @Deprecated
     public static void updateJar(String src, String dest,
                                  Map<String,Object> changes)
             throws IOException {
@@ -172,4 +316,26 @@
             }
         }
     }
+
+    /**
+     * Maps a file path to the equivalent name in a JAR file
+     */
+    private static String toJarEntryName(Path file) {
+        Path normalized = file.normalize();
+        return normalized.subpath(0, normalized.getNameCount())  // drop root
+                         .toString()
+                         .replace(File.separatorChar, '/');
+    }
+
+    private static List<Path> findAllRegularFiles(Path dir, Path[] files) throws IOException {
+        List<Path> entries = new ArrayList<>();
+        for (Path file : files) {
+            try (Stream<Path> stream = Files.find(dir.resolve(file), Integer.MAX_VALUE,
+                    (p, attrs) -> attrs.isRegularFile())) {
+                stream.map(dir::relativize)
+                      .forEach(entries::add);
+            }
+        }
+        return entries;
+    }
 }