jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java
changeset 36511 9d0388c6b336
parent 31673 135283550686
equal deleted inserted replaced
36510:043f1af70518 36511:9d0388c6b336
    39 import java.nio.file.DirectoryStream;
    39 import java.nio.file.DirectoryStream;
    40 import java.nio.file.Files;
    40 import java.nio.file.Files;
    41 import java.nio.file.FileSystem;
    41 import java.nio.file.FileSystem;
    42 import java.nio.file.FileSystems;
    42 import java.nio.file.FileSystems;
    43 import java.nio.file.Path;
    43 import java.nio.file.Path;
       
    44 import java.nio.file.ProviderNotFoundException;
    44 import java.nio.file.spi.FileSystemProvider;
    45 import java.nio.file.spi.FileSystemProvider;
    45 
    46 
    46 /**
    47 /**
    47  * This class is used to represent a class path, which can contain both
    48  * This class is used to represent a class path, which can contain both
    48  * directories and zip files.
    49  * directories and zip files.
    51  * supported API.  Code that depends on them does so at its own risk:
    52  * supported API.  Code that depends on them does so at its own risk:
    52  * they are subject to change or removal without notice.
    53  * they are subject to change or removal without notice.
    53  */
    54  */
    54 public
    55 public
    55 class ClassPath {
    56 class ClassPath {
    56     private static final String JIMAGE_EXT = ".jimage";
       
    57     private FileSystem getJrtFileSystem() {
    57     private FileSystem getJrtFileSystem() {
    58         return FileSystems.getFileSystem(URI.create("jrt:/"));
    58         return FileSystems.getFileSystem(URI.create("jrt:/"));
    59     }
    59     }
    60 
    60 
    61     static final char dirSeparator = File.pathSeparatorChar;
    61     static final char dirSeparator = File.pathSeparatorChar;
    96      * Build a default class path from the path strings specified by
    96      * Build a default class path from the path strings specified by
    97      * the properties sun.boot.class.path and env.class.path, in that
    97      * the properties sun.boot.class.path and env.class.path, in that
    98      * order.
    98      * order.
    99      */
    99      */
   100     public ClassPath() {
   100     public ClassPath() {
       
   101         // though this property is removed. Check for null and use only
       
   102         // if it is not null (when bootstrap JDK is used).
   101         String syscp = System.getProperty("sun.boot.class.path");
   103         String syscp = System.getProperty("sun.boot.class.path");
   102         String envcp = System.getProperty("env.class.path");
   104         String envcp = System.getProperty("env.class.path");
   103         if (envcp == null) envcp = ".";
   105         if (envcp == null) envcp = ".";
   104         String cp = syscp + File.pathSeparator + envcp;
   106 
       
   107         // add syscp only if not null!
       
   108         String cp = syscp == null? envcp : (syscp + File.pathSeparator + envcp);
   105         init(cp);
   109         init(cp);
   106     }
   110     }
   107 
   111 
   108     private void init(String pathstr) {
   112     private void init(String pathstr) {
   109         int i, j, n;
   113         int i, j, n;
   119         while ((i = pathstr.indexOf(dirSeparator, i)) != -1) {
   123         while ((i = pathstr.indexOf(dirSeparator, i)) != -1) {
   120             n++; i++;
   124             n++; i++;
   121         }
   125         }
   122         // Build the class path
   126         // Build the class path
   123         ClassPathEntry[] path = new ClassPathEntry[n+1];
   127         ClassPathEntry[] path = new ClassPathEntry[n+1];
       
   128 
   124         int len = pathstr.length();
   129         int len = pathstr.length();
   125         boolean jrtAdded = false;
       
   126         for (i = n = 0; i < len; i = j + 1) {
   130         for (i = n = 0; i < len; i = j + 1) {
   127             if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {
   131             if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {
   128                 j = len;
   132                 j = len;
   129             }
   133             }
   130             if (i == j) {
   134             if (i == j) {
   131                 path[n++] = new DirClassPathEntry(new File("."));
   135                 path[n++] = new DirClassPathEntry(new File("."));
   132             } else {
   136             } else {
   133                 String filename = pathstr.substring(i, j);
   137                 String filename = pathstr.substring(i, j);
   134                 File file = new File(filename);
   138                 File file = new File(filename);
   135                 if (file.isFile()) {
   139                 if (file.isFile()) {
   136                     if (filename.endsWith(JIMAGE_EXT)) {
   140                     try {
   137                         if (jrtAdded) continue;
   141                         ZipFile zip = new ZipFile(file);
   138                         FileSystem fs = getJrtFileSystem();
   142                         path[n++] = new ZipClassPathEntry(zip);
   139                         path[n++] = new JrtClassPathEntry(fs);
   143                     } catch (ZipException e) {
   140                         jrtAdded = true;
   144                     } catch (IOException e) {
   141                     } else {
   145                         // Ignore exceptions, at least for now...
   142                         try {
       
   143                             ZipFile zip = new ZipFile(file);
       
   144                             path[n++] = new ZipClassPathEntry(zip);
       
   145                         } catch (ZipException e) {
       
   146                         } catch (IOException e) {
       
   147                             // Ignore exceptions, at least for now...
       
   148                         }
       
   149                     }
   146                     }
   150                 } else {
   147                 } else {
   151                     path[n++] = new DirClassPathEntry(file);
   148                     path[n++] = new DirClassPathEntry(file);
   152                 }
   149                 }
   153             }
   150             }
   154         }
   151         }
       
   152 
       
   153         // add jrt file system at the end
       
   154         try {
       
   155             FileSystem fs = getJrtFileSystem();
       
   156             path[n++] = new JrtClassPathEntry(fs);
       
   157         } catch (ProviderNotFoundException ignored) {
       
   158             // this could happen during jdk build with earlier JDK as bootstrap
       
   159         }
       
   160 
   155         // Trim class path to exact size
   161         // Trim class path to exact size
   156         this.path = new ClassPathEntry[n];
   162         this.path = new ClassPathEntry[n];
   157         System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
   163         System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
   158     }
   164     }
   159 
   165 
   169             }
   175             }
   170             this.pathstr = sb.toString();
   176             this.pathstr = sb.toString();
   171         }
   177         }
   172 
   178 
   173         // Build the class path
   179         // Build the class path
   174         ClassPathEntry[] path = new ClassPathEntry[patharray.length];
   180         ClassPathEntry[] path = new ClassPathEntry[patharray.length + 1];
   175         int n = 0;
   181         int n = 0;
   176         boolean jrtAdded = false;
       
   177         for (String name : patharray) {
   182         for (String name : patharray) {
   178             File file = new File(name);
   183             File file = new File(name);
   179             if (file.isFile()) {
   184             if (file.isFile()) {
   180                 if (name.endsWith(JIMAGE_EXT)) {
   185                 try {
   181                     if (jrtAdded) continue;
   186                     ZipFile zip = new ZipFile(file);
   182                     FileSystem fs = getJrtFileSystem();
   187                     path[n++] = new ZipClassPathEntry(zip);
   183                     path[n++] = new JrtClassPathEntry(fs);
   188                 } catch (ZipException e) {
   184                     jrtAdded = true;
   189                 } catch (IOException e) {
   185                 } else {
   190                     // Ignore exceptions, at least for now...
   186                     try {
   191                 }
   187                         ZipFile zip = new ZipFile(file);
       
   188                         path[n++] = new ZipClassPathEntry(zip);
       
   189                     } catch (ZipException e) {
       
   190                     } catch (IOException e) {
       
   191                         // Ignore exceptions, at least for now...
       
   192                     }
       
   193                }
       
   194             } else {
   192             } else {
   195                 path[n++] = new DirClassPathEntry(file);
   193                 path[n++] = new DirClassPathEntry(file);
   196             }
   194             }
   197         }
   195         }
       
   196 
       
   197         // add jrt file system at the end
       
   198         try {
       
   199             FileSystem fs = getJrtFileSystem();
       
   200             path[n++] = new JrtClassPathEntry(fs);
       
   201         } catch (ProviderNotFoundException ignored) {
       
   202             // this could happen with earlier version of JDK used as bootstrap
       
   203         }
       
   204 
   198         // Trim class path to exact size
   205         // Trim class path to exact size
   199         this.path = new ClassPathEntry[n];
   206         this.path = new ClassPathEntry[n];
   200         System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
   207         System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
   201     }
   208     }
   202 
   209 
   381 }
   388 }
   382 
   389 
   383 // a ClassPathEntry that represents jrt file system
   390 // a ClassPathEntry that represents jrt file system
   384 final class JrtClassPathEntry extends ClassPathEntry {
   391 final class JrtClassPathEntry extends ClassPathEntry {
   385     private final FileSystem fs;
   392     private final FileSystem fs;
   386     // module directory paths in jrt fs
       
   387     private final Set<Path> jrtModules;
       
   388     // package name to package directory path mapping (lazily filled)
   393     // package name to package directory path mapping (lazily filled)
   389     private final Map<String, Path> pkgDirs;
   394     private final Map<String, Path> pkgDirs;
   390 
   395 
   391     JrtClassPathEntry(FileSystem fs) {
   396     JrtClassPathEntry(FileSystem fs) {
   392         this.fs = fs;
   397         this.fs = fs;
   393         this.jrtModules = new LinkedHashSet<>();
       
   394         this.pkgDirs = new HashMap<>();
   398         this.pkgDirs = new HashMap<>();
   395 
       
   396         // fill in module directories at the root dir
       
   397         Path root = fs.getPath("/modules");
       
   398         try {
       
   399             try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
       
   400                 for (Path entry: stream) {
       
   401                     if (Files.isDirectory(entry))
       
   402                         jrtModules.add(entry);
       
   403                 }
       
   404             }
       
   405         } catch (IOException ioExp) {
       
   406             throw new UncheckedIOException(ioExp);
       
   407         }
       
   408     }
   399     }
   409 
   400 
   410     void close() throws IOException {
   401     void close() throws IOException {
   411     }
   402     }
   412 
   403 
   415         // check the cache first
   406         // check the cache first
   416         if (pkgDirs.containsKey(pkgName)) {
   407         if (pkgDirs.containsKey(pkgName)) {
   417             return pkgDirs.get(pkgName);
   408             return pkgDirs.get(pkgName);
   418         }
   409         }
   419 
   410 
   420         for (Path modPath : jrtModules) {
   411         Path pkgLink = fs.getPath("/packages/" + pkgName.replace('/', '.'));
   421             Path pkgDir = fs.getPath(modPath.toString(), pkgName);
   412         // check if /packages/$PACKAGE directory exists
   422             // check if package directory is under any of the known modules
   413         if (Files.isDirectory(pkgLink)) {
   423             if (Files.exists(pkgDir)) {
   414            try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgLink)) {
   424                 // it is a package directory only if contains atleast one .class file
   415                 for (Path p : stream) {
   425                 try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgDir)) {
   416                     // find first symbolic link to module directory
   426                     for (Path p : stream) {
   417                     if (Files.isSymbolicLink(p)) {
   427                         if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
   418                         Path modDir = Files.readSymbolicLink(p);
   428                             // cache package-to-package dir mapping for future
   419                         if (Files.isDirectory(modDir)) {
   429                             pkgDirs.put(pkgName, pkgDir);
   420                             // get package subdirectory under /modules/$MODULE/
   430                             return pkgDir;
   421                             Path pkgDir = fs.getPath(modDir.toString() + "/" + pkgName);
       
   422                             if (Files.isDirectory(pkgDir)) {
       
   423                                 // it is a package directory only if contains
       
   424                                 // at least one .class file
       
   425                                 try (DirectoryStream<Path> pstream =
       
   426                                         Files.newDirectoryStream(pkgDir)) {
       
   427                                     for (Path f : pstream) {
       
   428                                         if (Files.isRegularFile(f)
       
   429                                                 && f.toString().endsWith(".class")) {
       
   430                                             pkgDirs.put(pkgName, pkgDir);
       
   431                                             return pkgDir;
       
   432                                         }
       
   433                                     }
       
   434                                 }
       
   435                             }
   431                         }
   436                         }
   432                     }
   437                     }
   433                 }
   438                 }
   434             }
   439             }
   435         }
   440         }