langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
changeset 27579 d1a63c99cdd5
parent 27226 53535e4e1b08
child 27858 443efec4bf09
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Tue Nov 18 15:25:18 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Wed Dec 03 14:25:46 2014 +0000
@@ -27,8 +27,12 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 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.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -41,6 +45,8 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 
 import javax.tools.JavaFileManager;
@@ -94,6 +100,12 @@
      */
     private boolean warn;
 
+    // Used by Locations(for now) to indicate that the PLATFORM_CLASS_PATH
+    // should use the jrt: file system.
+    // When Locations has been converted to use java.nio.file.Path,
+    // Locations can use Paths.get(URI.create("jrt:"))
+    static final File JRT_MARKER_FILE = new File("JRT_MARKER_FILE");
+
     public Locations() {
         initHandlers();
     }
@@ -115,12 +127,6 @@
         return h.isDefault();
     }
 
-    boolean isDefaultBootClassPathRtJar(File file) {
-        BootClassPathLocationHandler h
-                = (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH);
-        return h.isDefaultRtJar(file);
-    }
-
     public Collection<File> userClassPath() {
         return getLocation(CLASS_PATH);
     }
@@ -283,7 +289,7 @@
 
             if (fsInfo.isFile(file)) {
                 /* File is an ordinary file. */
-                if (!isArchive(file)) {
+                if (!isArchive(file) && !file.getName().endsWith(".jimage")) {
                     /* Not a recognized extension; open it to see if
                      it looks like a valid zip file. */
                     try {
@@ -309,7 +315,7 @@
             super.add(file);
             canonicalValues.add(canonFile);
 
-            if (expandJarClassPaths && fsInfo.isFile(file)) {
+            if (expandJarClassPaths && fsInfo.isFile(file) && !file.getName().endsWith(".jimage")) {
                 addJarClassPath(file, warn);
             }
         }
@@ -543,15 +549,9 @@
         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.
+         * Is the bootclasspath the default?
          */
-        private File defaultBootClassPathRtJar = null;
-
-        /**
-         * Is bootclasspath the default?
-         */
-        private boolean isDefaultBootClassPath;
+        private boolean isDefault;
 
         BootClassPathLocationHandler() {
             super(StandardLocation.PLATFORM_CLASS_PATH,
@@ -564,12 +564,7 @@
 
         boolean isDefault() {
             lazy();
-            return isDefaultBootClassPath;
-        }
-
-        boolean isDefaultRtJar(File file) {
-            lazy();
-            return file.equals(defaultBootClassPathRtJar);
+            return isDefault;
         }
 
         @Override
@@ -614,16 +609,16 @@
             if (files == null) {
                 searchPath = null;  // reset to "uninitialized"
             } else {
-                defaultBootClassPathRtJar = null;
-                isDefaultBootClassPath = false;
+                isDefault = false;
                 SearchPath p = new SearchPath().addFiles(files, false);
                 searchPath = Collections.unmodifiableCollection(p);
                 optionValues.clear();
             }
         }
 
-        SearchPath computePath() {
-            defaultBootClassPathRtJar = null;
+        SearchPath computePath() throws IOException {
+            String java_home = System.getProperty("java.home");
+
             SearchPath path = new SearchPath();
 
             String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
@@ -643,13 +638,13 @@
                 path.addFiles(bootclasspathOpt);
             } else {
                 // 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)) {
-                        defaultBootClassPathRtJar = file;
-                    }
+                Collection<File> systemClasses = systemClasses(java_home);
+                if (systemClasses != null) {
+                    path.addFiles(systemClasses, false);
+                } else {
+                    // fallback to the value of sun.boot.class.path
+                    String files = System.getProperty("sun.boot.class.path");
+                    path.addFiles(files, false);
                 }
             }
 
@@ -661,20 +656,69 @@
             if (extdirsOpt != null) {
                 path.addDirectories(extdirsOpt);
             } else {
+                // Add lib/jfxrt.jar to the search path
+                File jfxrt = new File(new File(java_home, "lib"), "jfxrt.jar");
+                if (jfxrt.exists()) {
+                    path.addFile(jfxrt, false);
+                }
                 path.addDirectories(System.getProperty("java.ext.dirs"), false);
             }
 
-            isDefaultBootClassPath
-                    = (xbootclasspathPrependOpt == null)
+            isDefault =
+                       (xbootclasspathPrependOpt == null)
                     && (bootclasspathOpt == null)
                     && (xbootclasspathAppendOpt == null);
 
             return path;
         }
 
+        /**
+         * Return a collection of files containing system classes.
+         * Returns {@code null} if not running on a modular image.
+         *
+         * @throws UncheckedIOException if an I/O errors occurs
+         */
+        private Collection<File> systemClasses(String java_home) throws IOException {
+            // Return .jimage files if available
+            Path libModules = Paths.get(java_home, "lib", "modules");
+            if (Files.exists(libModules)) {
+                try (Stream<Path> files = Files.list(libModules)) {
+                    boolean haveJImageFiles =
+                            files.anyMatch(f -> f.getFileName().toString().endsWith(".jimage"));
+                    if (haveJImageFiles) {
+                        return Collections.singleton(JRT_MARKER_FILE);
+                    }
+                }
+            }
+
+            // Temporary: if no .jimage files, return individual modules
+            if (Files.exists(libModules.resolve("java.base"))) {
+                return Files.list(libModules)
+                            .map(d -> d.resolve("classes"))
+                            .map(Path::toFile)
+                            .collect(Collectors.toList());
+            }
+
+            // Exploded module image
+            Path modules = Paths.get(java_home, "modules");
+            if (Files.isDirectory(modules.resolve("java.base"))) {
+                return Files.list(modules)
+                            .map(Path::toFile)
+                            .collect(Collectors.toList());
+            }
+
+            // not a modular image that we know about
+            return null;
+        }
+
         private void lazy() {
             if (searchPath == null) {
+                try {
                 searchPath = Collections.unmodifiableCollection(computePath());
+                } catch (IOException e) {
+                    // TODO: need better handling here, e.g. javac Abort?
+                    throw new UncheckedIOException(e);
+                }
             }
         }
     }