langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
changeset 27852 2e6ad0e4fe20
parent 27226 53535e4e1b08
child 27858 443efec4bf09
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri Nov 21 12:36:21 2014 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri Nov 21 10:38:43 2014 -0800
@@ -29,6 +29,10 @@
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -40,7 +44,8 @@
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 
 import javax.tools.JavaFileManager;
@@ -105,7 +110,7 @@
         this.fsInfo = fsInfo;
     }
 
-    public Collection<File> bootClassPath() {
+    public Collection<Path> bootClassPath() {
         return getLocation(PLATFORM_CLASS_PATH);
     }
 
@@ -115,56 +120,52 @@
         return h.isDefault();
     }
 
-    boolean isDefaultBootClassPathRtJar(File file) {
+    boolean isDefaultBootClassPathRtJar(Path file) {
         BootClassPathLocationHandler h
                 = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
         return h.isDefaultRtJar(file);
     }
 
-    public Collection<File> userClassPath() {
+    public Collection<Path> userClassPath() {
         return getLocation(CLASS_PATH);
     }
 
-    public Collection<File> sourcePath() {
-        Collection<File> p = getLocation(SOURCE_PATH);
+    public Collection<Path> sourcePath() {
+        Collection<Path> p = getLocation(SOURCE_PATH);
         // TODO: this should be handled by the LocationHandler
         return p == null || p.isEmpty() ? null : p;
     }
 
     /**
-     * Split a path into its elements. Empty path elements will be ignored.
+     * Split a search path into its elements. Empty path elements will be ignored.
      *
-     * @param path The path to be split
+     * @param searchPath The search path to be split
      * @return The elements of the path
      */
-    private static Iterable<File> getPathEntries(String path) {
-        return getPathEntries(path, null);
+    private static Iterable<Path> getPathEntries(String searchPath) {
+        return getPathEntries(searchPath, null);
     }
 
     /**
-     * Split a path into its elements. If emptyPathDefault is not null, all empty elements in the
+     * Split a search path into its elements. If emptyPathDefault is not null, all empty elements in the
      * path, including empty elements at either end of the path, will be replaced with the value of
      * emptyPathDefault.
      *
-     * @param path The path to be split
+     * @param searchPath The search path to be split
      * @param emptyPathDefault The value to substitute for empty path elements, or null, to ignore
      * empty path elements
      * @return The elements of the path
      */
-    private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
-        ListBuffer<File> entries = new ListBuffer<>();
-        int start = 0;
-        while (start <= path.length()) {
-            int sep = path.indexOf(File.pathSeparatorChar, start);
-            if (sep == -1) {
-                sep = path.length();
+    private static Iterable<Path> getPathEntries(String searchPath, Path emptyPathDefault) {
+        ListBuffer<Path> entries = new ListBuffer<>();
+        for (String s: searchPath.split(Pattern.quote(File.pathSeparator), -1)) {
+            if (s.isEmpty()) {
+                if (emptyPathDefault != null) {
+                    entries.add(emptyPathDefault);
+                }
+            } else {
+                entries.add(Paths.get(s));
             }
-            if (start < sep) {
-                entries.add(new File(path.substring(start, sep)));
-            } else if (emptyPathDefault != null) {
-                entries.add(emptyPathDefault);
-            }
-            start = sep + 1;
         }
         return entries;
     }
@@ -173,12 +174,12 @@
      * Utility class to help evaluate a path option. Duplicate entries are ignored, jar class paths
      * can be expanded.
      */
-    private class SearchPath extends LinkedHashSet<File> {
+    private class SearchPath extends LinkedHashSet<Path> {
 
         private static final long serialVersionUID = 0;
 
         private boolean expandJarClassPaths = false;
-        private final Set<File> canonicalValues = new HashSet<>();
+        private final Set<Path> canonicalValues = new HashSet<>();
 
         public SearchPath expandJarClassPaths(boolean x) {
             expandJarClassPaths = x;
@@ -188,9 +189,9 @@
         /**
          * What to use when path element is the empty string
          */
-        private File emptyPathDefault = null;
+        private Path emptyPathDefault = null;
 
-        public SearchPath emptyPathDefault(File x) {
+        public SearchPath emptyPathDefault(Path x) {
             emptyPathDefault = x;
             return this;
         }
@@ -200,7 +201,7 @@
             expandJarClassPaths = true;
             try {
                 if (dirs != null) {
-                    for (File dir : getPathEntries(dirs)) {
+                    for (Path dir : getPathEntries(dirs)) {
                         addDirectory(dir, warn);
                     }
                 }
@@ -214,8 +215,8 @@
             return addDirectories(dirs, warn);
         }
 
-        private void addDirectory(File dir, boolean warn) {
-            if (!dir.isDirectory()) {
+        private void addDirectory(Path dir, boolean warn) {
+            if (!Files.isDirectory(dir)) {
                 if (warn) {
                     log.warning(Lint.LintCategory.PATH,
                             "dir.path.element.not.found", dir);
@@ -223,15 +224,10 @@
                 return;
             }
 
-            File[] files = dir.listFiles();
-            if (files == null) {
-                return;
-            }
-
-            for (File direntry : files) {
-                if (isArchive(direntry)) {
-                    addFile(direntry, warn);
-                }
+            try (Stream<Path> s = Files.list(dir)) {
+                s.filter(dirEntry -> isArchive(dirEntry))
+                        .forEach(dirEntry -> addFile(dirEntry, warn));
+            } catch (IOException ignore) {
             }
         }
 
@@ -246,20 +242,20 @@
             return addFiles(files, warn);
         }
 
-        public SearchPath addFiles(Iterable<? extends File> files, boolean warn) {
+        public SearchPath addFiles(Iterable<? extends Path> files, boolean warn) {
             if (files != null) {
-                for (File file : files) {
+                for (Path file : files) {
                     addFile(file, warn);
                 }
             }
             return this;
         }
 
-        public SearchPath addFiles(Iterable<? extends File> files) {
+        public SearchPath addFiles(Iterable<? extends Path> files) {
             return addFiles(files, warn);
         }
 
-        public void addFile(File file, boolean warn) {
+        public void addFile(Path file, boolean warn) {
             if (contains(file)) {
                 // discard duplicates
                 return;
@@ -275,7 +271,7 @@
                 return;
             }
 
-            File canonFile = fsInfo.getCanonicalFile(file);
+            Path canonFile = fsInfo.getCanonicalFile(file);
             if (canonicalValues.contains(canonFile)) {
                 /* Discard duplicates and avoid infinite recursion */
                 return;
@@ -287,7 +283,7 @@
                     /* Not a recognized extension; open it to see if
                      it looks like a valid zip file. */
                     try {
-                        ZipFile z = new ZipFile(file);
+                        ZipFile z = new ZipFile(file.toFile());
                         z.close();
                         if (warn) {
                             log.warning(Lint.LintCategory.PATH,
@@ -318,9 +314,9 @@
         // Manifest entry.  In some future release, we may want to
         // update this code to recognize URLs rather than simple
         // filenames, but if we do, we should redo all path-related code.
-        private void addJarClassPath(File jarFile, boolean warn) {
+        private void addJarClassPath(Path jarFile, boolean warn) {
             try {
-                for (File f : fsInfo.getJarClassPath(jarFile)) {
+                for (Path f : fsInfo.getJarClassPath(jarFile)) {
                     addFile(f, warn);
                 }
             } catch (IOException e) {
@@ -365,12 +361,12 @@
         /**
          * @see StandardJavaFileManager#getLocation
          */
-        abstract Collection<File> getLocation();
+        abstract Collection<Path> getLocation();
 
         /**
          * @see StandardJavaFileManager#setLocation
          */
-        abstract void setLocation(Iterable<? extends File> files) throws IOException;
+        abstract void setLocation(Iterable<? extends Path> files) throws IOException;
     }
 
     /**
@@ -380,7 +376,7 @@
      */
     private class OutputLocationHandler extends LocationHandler {
 
-        private File outputDir;
+        private Path outputDir;
 
         OutputLocationHandler(Location location, Option... options) {
             super(location, options);
@@ -396,31 +392,31 @@
             // need to decide how best to report issue for benefit of
             // direct API call on JavaFileManager.handleOption(specifies IAE)
             // vs. command line decoding.
-            outputDir = (value == null) ? null : new File(value);
+            outputDir = (value == null) ? null : Paths.get(value);
             return true;
         }
 
         @Override
-        Collection<File> getLocation() {
+        Collection<Path> getLocation() {
             return (outputDir == null) ? null : Collections.singleton(outputDir);
         }
 
         @Override
-        void setLocation(Iterable<? extends File> files) throws IOException {
+        void setLocation(Iterable<? extends Path> files) throws IOException {
             if (files == null) {
                 outputDir = null;
             } else {
-                Iterator<? extends File> pathIter = files.iterator();
+                Iterator<? extends Path> pathIter = files.iterator();
                 if (!pathIter.hasNext()) {
                     throw new IllegalArgumentException("empty path for directory");
                 }
-                File dir = pathIter.next();
+                Path dir = pathIter.next();
                 if (pathIter.hasNext()) {
                     throw new IllegalArgumentException("path too long for directory");
                 }
-                if (!dir.exists()) {
+                if (!Files.exists(dir)) {
                     throw new FileNotFoundException(dir + ": does not exist");
-                } else if (!dir.isDirectory()) {
+                } else if (!Files.isDirectory(dir)) {
                     throw new IOException(dir + ": not a directory");
                 }
                 outputDir = dir;
@@ -435,7 +431,7 @@
      */
     private class SimpleLocationHandler extends LocationHandler {
 
-        protected Collection<File> searchPath;
+        protected Collection<Path> searchPath;
 
         SimpleLocationHandler(Location location, Option... options) {
             super(location, options);
@@ -452,12 +448,12 @@
         }
 
         @Override
-        Collection<File> getLocation() {
+        Collection<Path> getLocation() {
             return searchPath;
         }
 
         @Override
-        void setLocation(Iterable<? extends File> files) {
+        void setLocation(Iterable<? extends Path> files) {
             SearchPath p;
             if (files == null) {
                 p = computePath(null);
@@ -488,7 +484,7 @@
         }
 
         @Override
-        Collection<File> getLocation() {
+        Collection<Path> getLocation() {
             lazy();
             return searchPath;
         }
@@ -520,7 +516,7 @@
         protected SearchPath createPath() {
             return new SearchPath()
                     .expandJarClassPaths(true) // Only search user jars for Class-Paths
-                    .emptyPathDefault(new File("."));  // Empty path elt ==> current directory
+                    .emptyPathDefault(Paths.get("."));  // Empty path elt ==> current directory
         }
 
         private void lazy() {
@@ -539,14 +535,14 @@
      */
     private class BootClassPathLocationHandler extends LocationHandler {
 
-        private Collection<File> searchPath;
+        private Collection<Path> searchPath;
         final Map<Option, String> optionValues = new EnumMap<>(Option.class);
 
         /**
          * rt.jar as found on the default bootclasspath. If the user specified a bootclasspath, null
          * is used.
          */
-        private File defaultBootClassPathRtJar = null;
+        private Path defaultBootClassPathRtJar = null;
 
         /**
          * Is bootclasspath the default?
@@ -567,7 +563,7 @@
             return isDefaultBootClassPath;
         }
 
-        boolean isDefaultRtJar(File file) {
+        boolean isDefaultRtJar(Path file) {
             lazy();
             return file.equals(defaultBootClassPathRtJar);
         }
@@ -604,13 +600,13 @@
         }
 
         @Override
-        Collection<File> getLocation() {
+        Collection<Path> getLocation() {
             lazy();
             return searchPath;
         }
 
         @Override
-        void setLocation(Iterable<? extends File> files) {
+        void setLocation(Iterable<? extends Path> files) {
             if (files == null) {
                 searchPath = null;  // reset to "uninitialized"
             } else {
@@ -645,9 +641,9 @@
                 // Standard system classes for this compiler's release.
                 String files = System.getProperty("sun.boot.class.path");
                 path.addFiles(files, false);
-                File rt_jar = new File("rt.jar");
-                for (File file : getPathEntries(files)) {
-                    if (new File(file.getName()).equals(rt_jar)) {
+                Path rt_jar = Paths.get("rt.jar");
+                for (Path file : getPathEntries(files)) {
+                    if (file.getFileName().equals(rt_jar)) {
                         defaultBootClassPathRtJar = file;
                     }
                 }
@@ -709,12 +705,12 @@
         return (h == null ? false : h.handleOption(option, value));
     }
 
-    Collection<File> getLocation(Location location) {
+    Collection<Path> getLocation(Location location) {
         LocationHandler h = getHandler(location);
         return (h == null ? null : h.getLocation());
     }
 
-    File getOutputLocation(Location location) {
+    Path getOutputLocation(Location location) {
         if (!location.isOutputLocation()) {
             throw new IllegalArgumentException();
         }
@@ -722,7 +718,7 @@
         return ((OutputLocationHandler) h).outputDir;
     }
 
-    void setLocation(Location location, Iterable<? extends File> files) throws IOException {
+    void setLocation(Location location, Iterable<? extends Path> files) throws IOException {
         LocationHandler h = getHandler(location);
         if (h == null) {
             if (location.isOutputLocation()) {
@@ -743,8 +739,8 @@
     /**
      * Is this the name of an archive file?
      */
-    private boolean isArchive(File file) {
-        String n = StringUtils.toLowerCase(file.getName());
+    private boolean isArchive(Path file) {
+        String n = StringUtils.toLowerCase(file.getFileName().toString());
         return fsInfo.isFile(file)
                 && (n.endsWith(".jar") || n.endsWith(".zip"));
     }
@@ -753,50 +749,41 @@
      * Utility method for converting a search path string to an array of directory and JAR file
      * URLs.
      *
-     * Note that this method is called by apt and the DocletInvoker.
+     * Note that this method is called by the DocletInvoker.
      *
      * @param path the search path string
      * @return the resulting array of directory and JAR file URLs
      */
     public static URL[] pathToURLs(String path) {
-        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
-        URL[] urls = new URL[st.countTokens()];
-        int count = 0;
-        while (st.hasMoreTokens()) {
-            URL url = fileToURL(new File(st.nextToken()));
-            if (url != null) {
-                urls[count++] = url;
+        java.util.List<URL> urls = new ArrayList<>();
+        for (String s: path.split(Pattern.quote(File.pathSeparator))) {
+            if (!s.isEmpty()) {
+                URL url = fileToURL(Paths.get(s));
+                if (url != null) {
+                    urls.add(url);
+                }
             }
         }
-        urls = Arrays.copyOf(urls, count);
-        return urls;
+        return urls.toArray(new URL[urls.size()]);
     }
 
     /**
      * Returns the directory or JAR file URL corresponding to the specified local file name.
      *
-     * @param file the File object
+     * @param file the Path object
      * @return the resulting directory or JAR file URL, or null if unknown
      */
-    private static URL fileToURL(File file) {
-        String name;
+    private static URL fileToURL(Path file) {
+        Path p;
         try {
-            name = file.getCanonicalPath();
+            p = file.toRealPath();
         } catch (IOException e) {
-            name = file.getAbsolutePath();
-        }
-        name = name.replace(File.separatorChar, '/');
-        if (!name.startsWith("/")) {
-            name = "/" + name;
-        }
-        // If the file does not exist, then assume that it's a directory
-        if (!file.isFile()) {
-            name = name + "/";
+            p = file.toAbsolutePath();
         }
         try {
-            return new URL("file", "", name);
+            return p.normalize().toUri().toURL();
         } catch (MalformedURLException e) {
-            throw new IllegalArgumentException(file.toString());
+            return null;
         }
     }
 }