8218875: Add new FileSystems.newFileSystem methods
authorlancea
Thu, 02 May 2019 17:08:03 -0400
changeset 54693 d890ba18f64b
parent 54692 22866513a80e
child 54694 948644e20013
8218875: Add new FileSystems.newFileSystem methods Reviewed-by: rriggs, alanb, clanger, dfuchs
src/java.base/share/classes/java/nio/file/FileSystems.java
src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java
test/jdk/jdk/nio/zipfs/Basic.java
test/jdk/jdk/nio/zipfs/NewFileSystemTests.java
test/jdk/jdk/nio/zipfs/PathOps.java
test/jdk/jdk/nio/zipfs/ZipFSTester.java
test/langtools/tools/javac/api/file/SJFM_TestBase.java
test/langtools/tools/javac/modules/ContainsTest.java
--- a/src/java.base/share/classes/java/nio/file/FileSystems.java	Thu May 02 13:25:00 2019 -0700
+++ b/src/java.base/share/classes/java/nio/file/FileSystems.java	Thu May 02 17:08:03 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, 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
@@ -365,14 +365,13 @@
      * systems where the contents of one or more files is treated as a file
      * system.
      *
-     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
-     * installed} providers. It invokes, in turn, each provider's {@link
-     * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method
-     * with an empty map. If a provider returns a file system then the iteration
-     * terminates and the file system is returned. If none of the installed
-     * providers return a {@code FileSystem} then an attempt is made to locate
-     * the provider using the given class loader. If a provider returns a file
-     * system then the lookup terminates and the file system is returned.
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path, Map, ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method with an empty map. If none
+     * of the installed providers return a {@code FileSystem} then an attempt is
+     * made to locate the provider using the given class loader. If a provider
+     * returns a file system then the lookup terminates and the file system is
+     * returned.
      *
      * @param   path
      *          the path to the file
@@ -396,10 +395,131 @@
                                            ClassLoader loader)
         throws IOException
     {
+        return newFileSystem(path, Map.of(), loader);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
+     * {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
+     * method is invoked to construct the new file system.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   env
+     *          a map of provider specific properties to configure the file system;
+     *          may be empty
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path, Map<String,?> env)
+        throws IOException
+    {
+        return newFileSystem(path, env, null);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
+     * {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
+     * method is invoked with an empty map to construct the new file system.
+     *
+     * @param   path
+     *          the path to the file
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path) throws IOException {
+        return newFileSystem(path, Map.of(), null);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers. It invokes, in turn, each provider's {@link
+     * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)}
+     * method. If a provider returns a file system then the iteration
+     * terminates and the file system is returned.
+     * If none of the installed providers return a {@code FileSystem} then
+     * an attempt is made to locate the provider using the given class loader.
+     * If a provider returns a file
+     * system, then the lookup terminates and the file system is returned.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   env
+     *          a map of provider specific properties to configure the file system;
+     *          may be empty
+     * @param   loader
+     *          the class loader to locate the provider or {@code null} to only
+     *          attempt to locate an installed provider
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path, Map<String,?> env,
+                                           ClassLoader loader)
+        throws IOException
+    {
         if (path == null)
             throw new NullPointerException();
-        Map<String,?> env = Collections.emptyMap();
-
         // check installed providers
         for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
             try {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Thu May 02 13:25:00 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Thu May 02 17:08:03 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -566,7 +566,7 @@
                 Assert.checkNonNull(jarFSProvider, "should have been caught before!");
                 this.fileSystem = jarFSProvider.newFileSystem(archivePath, env);
             } else {
-                this.fileSystem = FileSystems.newFileSystem(archivePath, null);
+                this.fileSystem = FileSystems.newFileSystem(archivePath, (ClassLoader)null);
             }
             packages = new HashMap<>();
             for (Path root : fileSystem.getRootDirectories()) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Thu May 02 13:25:00 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Thu May 02 17:08:03 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -379,7 +379,7 @@
                         /* Not a recognized extension; open it to see if
                          it looks like a valid zip file. */
                         try {
-                            FileSystems.newFileSystem(file, null).close();
+                            FileSystems.newFileSystem(file, (ClassLoader)null).close();
                             if (warn) {
                                 log.warning(Lint.LintCategory.PATH,
                                             Warnings.UnexpectedArchiveFile(file));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Thu May 02 13:25:00 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Thu May 02 17:08:03 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -113,7 +113,7 @@
         SUPPORTED_JAVA_PLATFORM_VERSIONS = new TreeSet<>(NUMERICAL_COMPARATOR);
         Path ctSymFile = findCtSym();
         if (Files.exists(ctSymFile)) {
-            try (FileSystem fs = FileSystems.newFileSystem(ctSymFile, null);
+            try (FileSystem fs = FileSystems.newFileSystem(ctSymFile, (ClassLoader)null);
                  DirectoryStream<Path> dir =
                          Files.newDirectoryStream(fs.getRootDirectories().iterator().next())) {
                 for (Path section : dir) {
@@ -252,7 +252,7 @@
                 try {
                     FileSystem fs = ctSym2FileSystem.get(file);
                     if (fs == null) {
-                        ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, null));
+                        ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, (ClassLoader)null));
                     }
 
                     Path root = fs.getRootDirectories().iterator().next();
--- a/test/jdk/jdk/nio/zipfs/Basic.java	Thu May 02 13:25:00 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/Basic.java	Thu May 02 17:08:03 2019 -0400
@@ -69,7 +69,7 @@
 
         // Test: FileSystems#newFileSystem(Path)
         Map<String,?> env = Collections.emptyMap();
-        FileSystems.newFileSystem(jarFile, null).close();
+        FileSystems.newFileSystem(jarFile).close();
 
         // Test: FileSystems#newFileSystem(URI)
         URI uri = new URI("jar", jarFile.toUri().toString(), null);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/nio/zipfs/NewFileSystemTests.java	Thu May 02 17:08:03 2019 -0400
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2019, 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 org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.Map;
+
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8218875
+ * @summary ZIP File System tests that leverage Files.newFileSystem
+ * @modules jdk.zipfs
+ * @compile NewFileSystemTests.java
+ * @run testng NewFileSystemTests
+ * @run testng/othervm/java.security.policy=test.policy  NewFileSystemTests
+ */
+public class NewFileSystemTests {
+
+    // The Zip file system scheme
+    private static final String ZIPFS_SCHEME = "jar";
+    // Map to used for creating a ZIP archive
+    private static final Map<String, String> ZIPFS_OPTIONS = Map.of("create", "true");
+    // Primary jar file used for testing
+    private static Path jarFile;
+    // URI for jar file used for testing
+    private static URI jarURI;
+
+    /**
+     * Create the JAR file used by the tests
+     */
+    @BeforeClass
+    public void setUp() throws Exception {
+        jarFile = Utils.createJarFile("basic.jar",
+                "README");
+        jarURI = new URI(ZIPFS_SCHEME, jarFile.toUri().toString(), null);
+
+    }
+
+    /**
+     * Remove JAR file used by test as part of clean-up
+     */
+    @AfterClass
+    public void tearDown() throws Exception {
+        Files.deleteIfExists(jarFile);
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, Map<String, ?>)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNewFileSystemPathMap() throws IOException {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"),
+                ZIPFS_OPTIONS)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNewFileSystemPath() throws IOException {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"))) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, ClassLoader)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test(dataProvider = "classLoaders")
+    public void testNewFileSystemPathClassLoader(ClassLoader cl) throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"),
+                cl)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, Map<String, ?>, ClassLoader)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test(dataProvider = "classLoaders")
+    public void testNewFileSystemPathMapClassLoader(ClassLoader cl) throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(Path.of("basic.jar"),
+                ZIPFS_OPTIONS, cl)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(URI, Map<String, ?>)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNewFileSystemUriMap() throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(jarURI, ZIPFS_OPTIONS)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(URI, Map<String, ?>, ClassLoader)}
+     * will return a Zip file system
+     *
+     * @throws IOException
+     */
+    @Test(dataProvider = "classLoaders")
+    public void testNewFileSystemURIMapClassLoader(ClassLoader cl) throws Exception {
+        try (FileSystem zipfs = FileSystems.newFileSystem(jarURI, ZIPFS_OPTIONS,
+                cl)) {
+            checkFileSystem(zipfs);
+        }
+    }
+
+    /**
+     * Validate that {@code FileSystems.newFileSystem(Path, Map<String, ?>)}
+     * will throw a {@code NullPointerException} when the specified {@code Map}
+     * is null
+     *
+     */
+    @Test
+    public void testNewFileSystemPathNullMap() {
+        Map<String, ?> nullMap = null;
+        assertThrows(NullPointerException.class, () ->
+                FileSystems.newFileSystem(Path.of("basic.jar"), nullMap));
+    }
+
+    /*
+     * DataProvider used to verify that a Zip file system may be returned
+     * when specifying a class loader
+     */
+    @DataProvider(name = "classLoaders")
+    private Object[][] classLoaders() {
+        return new Object[][]{
+                {null},
+                {ClassLoader.getSystemClassLoader()}
+        };
+    }
+
+    /**
+     * Validate that the given FileSystem is a Zip file system.
+     *
+     * @param fs File System to validate
+     */
+    private void checkFileSystem(FileSystem fs) {
+
+        assertNotNull(fs, "Error: FileSystem was not returned");
+        assertTrue(fs.provider().getScheme().equalsIgnoreCase(ZIPFS_SCHEME));
+        assertTrue(fs.isOpen());
+        assertEquals(fs.getSeparator(), "/");
+
+        // one root
+        Iterator<Path> roots = fs.getRootDirectories().iterator();
+        assertTrue(roots.next().toString().equals("/"));
+        assertFalse(roots.hasNext());
+    }
+}
--- a/test/jdk/jdk/nio/zipfs/PathOps.java	Thu May 02 13:25:00 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/PathOps.java	Thu May 02 17:08:03 2019 -0400
@@ -604,7 +604,7 @@
         // create empty JAR file, test doesn't require any contents
         Path emptyJar = Utils.createJarFile("empty.jar");
 
-        fs = FileSystems.newFileSystem(emptyJar, null);
+        fs = FileSystems.newFileSystem(emptyJar);
         try {
             npes();
             mismatchedProviders();
--- a/test/jdk/jdk/nio/zipfs/ZipFSTester.java	Thu May 02 13:25:00 2019 -0700
+++ b/test/jdk/jdk/nio/zipfs/ZipFSTester.java	Thu May 02 17:08:03 2019 -0400
@@ -81,7 +81,6 @@
  */
 
 public class ZipFSTester {
-
     public static void main(String[] args) throws Exception {
         // create JAR file for test, actual contents don't matter
         Path jarFile = Utils.createJarFile("tester.jar",
@@ -146,7 +145,7 @@
             // copy the test jar itself in
             Files.copy(Paths.get(fs0.toString()), copy.getPath("/foo.jar"));
             Path zpath = copy.getPath("/foo.jar");
-            try (FileSystem zzfs = FileSystems.newFileSystem(zpath, null)) {
+            try (FileSystem zzfs = FileSystems.newFileSystem(zpath)) {
                 Files.copy(src, zzfs.getPath("/srcInjarjar"));
             }
         }
@@ -254,7 +253,7 @@
             // test foo.jar in jar/zipfs #8034802
             Path jpath = fs.getPath("/foo.jar");
             System.out.println("walking: " + jpath);
-            try (FileSystem zzfs = FileSystems.newFileSystem(jpath, null)) {
+            try (FileSystem zzfs = FileSystems.newFileSystem(jpath)) {
                 walk(zzfs.getPath("/"));
                 // foojar:/srcInjarjar
                 checkEqual(src, zzfs.getPath("/srcInjarjar"));
--- a/test/langtools/tools/javac/api/file/SJFM_TestBase.java	Thu May 02 13:25:00 2019 -0700
+++ b/test/langtools/tools/javac/api/file/SJFM_TestBase.java	Thu May 02 17:08:03 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -160,7 +160,7 @@
     List<Path> getTestZipPaths() throws IOException {
         if (zipfs == null) {
             Path testZip = createSourceZip();
-            zipfs = FileSystems.newFileSystem(testZip, null);
+            zipfs = FileSystems.newFileSystem(testZip);
             closeables.add(zipfs);
             zipPaths = Files.list(zipfs.getRootDirectories().iterator().next())
                 .filter(p -> p.getFileName().toString().endsWith(".java"))
--- a/test/langtools/tools/javac/modules/ContainsTest.java	Thu May 02 13:25:00 2019 -0700
+++ b/test/langtools/tools/javac/modules/ContainsTest.java	Thu May 02 17:08:03 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -129,7 +129,7 @@
         Path c = src.resolve("p/C.java");
         Path x = base.resolve("src2/p/C.java");
 
-        try (FileSystem jarFS = FileSystems.newFileSystem(jar, null);
+        try (FileSystem jarFS = FileSystems.newFileSystem(jar);
                 StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
             Path jarRoot = jarFS.getRootDirectories().iterator().next();
             fm.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(src, jarRoot));