< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java

Print this page




 415         /**
 416          * @see StandardJavaFileManager#getLocation
 417          */
 418         abstract Collection<Path> getPaths();
 419 
 420         /**
 421          * @see StandardJavaFileManager#setLocation
 422          */
 423         abstract void setPaths(Iterable<? extends Path> files) throws IOException;
 424 
 425         /**
 426          * @see JavaFileManager#getLocationForModule(Location, String)
 427          */
 428         Location getLocationForModule(String moduleName) throws IOException {
 429             return null;
 430         }
 431 
 432         /**
 433          * @see JavaFileManager#getLocationForModule(Location, JavaFileObject, String)
 434          */
 435         Location getLocationForModule(Path dir) {
 436             return null;
 437         }
 438 
 439         /**
 440          * @see JavaFileManager#inferModuleName
 441          */
 442         String inferModuleName() {
 443             return null;
 444         }
 445 
 446         /**
 447          * @see JavaFileManager#listLocationsForModules
 448          */
 449         Iterable<Set<Location>> listLocationsForModules() throws IOException {
 450             return null;
 451         }
 452     }
 453 
 454     /**
 455      * A LocationHandler for a given Location, and associated set of options.


 528                     throw new IOException(dir + ": not a directory");
 529                 }
 530                 outputDir = dir;
 531             }
 532             moduleLocations = null;
 533             pathLocations = null;
 534         }
 535 
 536         @Override
 537         Location getLocationForModule(String name) {
 538             if (moduleLocations == null) {
 539                 moduleLocations = new HashMap<>();
 540                 pathLocations = new HashMap<>();
 541             }
 542             Location l = moduleLocations.get(name);
 543             if (l == null) {
 544                 Path out = outputDir.resolve(name);
 545                 l = new ModuleLocationHandler(location.getName() + "[" + name + "]",
 546                         name,
 547                         Collections.singleton(out),
 548                         true, false);
 549                 moduleLocations.put(name, l);
 550                 pathLocations.put(out.toAbsolutePath(), l);
 551            }
 552             return l;
 553         }
 554 
 555         @Override
 556         Location getLocationForModule(Path dir) {
 557             return (pathLocations == null) ? null : pathLocations.get(dir);
 558         }
 559 
 560         private boolean listed;
 561 
 562         @Override
 563         Iterable<Set<Location>> listLocationsForModules() throws IOException {
 564             if (!listed && outputDir != null) {
 565                 try (DirectoryStream<Path> stream = Files.newDirectoryStream(outputDir)) {
 566                     for (Path p : stream) {
 567                         getLocationForModule(p.getFileName().toString());
 568                     }


 847                 } catch (IOException e) {
 848                     // TODO: need better handling here, e.g. javac Abort?
 849                     throw new UncheckedIOException(e);
 850                 }
 851             }
 852         }
 853     }
 854 
 855     /**
 856      * A LocationHander to represent modules found from a module-oriented
 857      * location such as MODULE_SOURCE_PATH, UPGRADE_MODULE_PATH,
 858      * SYSTEM_MODULES and MODULE_PATH.
 859      *
 860      * The Location can be specified to accept overriding classes from the
 861      * {@code --patch-module <module>=<path> } parameter.
 862      */
 863     private class ModuleLocationHandler extends LocationHandler implements Location {
 864         protected final String name;
 865         protected final String moduleName;
 866         protected final Collection<Path> searchPath;
 867         protected final Collection<Path> searchPathWithOverrides;
 868         protected final boolean output;
 869 
 870         ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath,
 871                 boolean output, boolean allowOverrides) {
 872             this.name = name;
 873             this.moduleName = moduleName;
 874             this.searchPath = searchPath;
 875             this.output = output;
 876 
 877             if (allowOverrides && patchMap != null) {
 878                 SearchPath mPatch = patchMap.get(moduleName);
 879                 if (mPatch != null) {
 880                     SearchPath sp = new SearchPath();
 881                     sp.addAll(mPatch);
 882                     sp.addAll(searchPath);
 883                     searchPathWithOverrides = sp;
 884                 } else {
 885                     searchPathWithOverrides = searchPath;
 886                 }
 887             } else {
 888                 searchPathWithOverrides = searchPath;
 889             }
 890         }
 891 
 892         @Override @DefinedBy(Api.COMPILER)
 893         public String getName() {
 894             return name;
 895         }
 896 
 897         @Override @DefinedBy(Api.COMPILER)
 898         public boolean isOutputLocation() {
 899             return output;
 900         }
 901 
 902         @Override // defined by LocationHandler
 903         boolean handleOption(Option option, String value) {
 904             throw new UnsupportedOperationException();
 905         }
 906 
 907         @Override // defined by LocationHandler
 908         Collection<Path> getPaths() {
 909             // For now, we always return searchPathWithOverrides. This may differ from the
 910             // JVM behavior if there is a module-info.class to be found in the overriding
 911             // classes.
 912             return searchPathWithOverrides;
 913         }
 914 
 915         @Override // defined by LocationHandler
 916         void setPaths(Iterable<? extends Path> files) throws IOException {
 917             throw new UnsupportedOperationException();
 918         }
 919 
 920         @Override // defined by LocationHandler
 921         String inferModuleName() {
 922             return moduleName;
 923         }
 924     }
 925 
 926     /**
 927      * A LocationHandler for simple module-oriented search paths,
 928      * like UPGRADE_MODULE_PATH and MODULE_PATH.
 929      */
 930     private class ModulePathLocationHandler extends SimpleLocationHandler {
 931         private Map<String, ModuleLocationHandler> pathModules;
 932 


1046                         if (entry.endsWith("module-info.class")) {
1047                             moduleInfoClass = entry;
1048                             break;  // no need to continue scanning
1049                         }
1050                         paths.add(entry);
1051                     }
1052                 } catch (DirectoryIteratorException | IOException ignore) {
1053                     log.error(Errors.LocnCantReadDirectory(path));
1054                     return Collections.emptySet();
1055                 }
1056 
1057                 if (moduleInfoClass != null) {
1058                     // It's an exploded module directly on the module path.
1059                     // We can't infer module name from the directory name, so have to
1060                     // read module-info.class.
1061                     try {
1062                         String moduleName = readModuleName(moduleInfoClass);
1063                         String name = location.getName()
1064                                 + "[" + pathIndex + ":" + moduleName + "]";
1065                         ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
1066                                 Collections.singleton(path), false, true);
1067                         return Collections.singleton(l);
1068                     } catch (ModuleNameReader.BadClassFile e) {
1069                         log.error(Errors.LocnBadModuleInfo(path));
1070                         return Collections.emptySet();
1071                     } catch (IOException e) {
1072                         log.error(Errors.LocnCantReadFile(path));
1073                         return Collections.emptySet();
1074                     }
1075                 }
1076 
1077                 // A directory of modules
1078                 Set<Location> result = new LinkedHashSet<>();
1079                 int index = 0;
1080                 for (Path entry : paths) {
1081                     Pair<String,Path> module = inferModuleName(entry);
1082                     if (module == null) {
1083                         // diagnostic reported if necessary; skip to next
1084                         continue;
1085                     }
1086                     String moduleName = module.fst;
1087                     Path modulePath = module.snd;
1088                     String name = location.getName()
1089                             + "[" + pathIndex + "." + (index++) + ":" + moduleName + "]";
1090                     ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
1091                             Collections.singleton(modulePath), false, true);
1092                     result.add(l);
1093                 }
1094                 return result;
1095             }
1096 
1097             private Set<Location> scanFile(Path path) {
1098                 Pair<String,Path> module = inferModuleName(path);
1099                 if (module == null) {
1100                     // diagnostic reported if necessary
1101                     return Collections.emptySet();
1102                 }
1103                 String moduleName = module.fst;
1104                 Path modulePath = module.snd;
1105                 String name = location.getName()
1106                         + "[" + pathIndex + ":" + moduleName + "]";
1107                 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
1108                         Collections.singleton(modulePath), false, true);
1109                 return Collections.singleton(l);
1110             }
1111 
1112             private Pair<String,Path> inferModuleName(Path p) {
1113                 if (Files.isDirectory(p)) {
1114                     if (Files.exists(p.resolve("module-info.class"))) {
1115                         String name = p.getFileName().toString();
1116                         if (SourceVersion.isName(name))
1117                             return new Pair<>(name, p);
1118                     }
1119                     return null;
1120                 }
1121 
1122                 if (p.getFileName().toString().endsWith(".jar") && fsInfo.exists(p)) {
1123                     FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider();
1124                     if (jarFSProvider == null) {
1125                         log.error(Errors.NoZipfsForArchive(p));
1126                         return null;
1127                     }
1128                     try (FileSystem fs = jarFSProvider.newFileSystem(p, fsEnv)) {


1255                     }
1256                     Path prefix = getPath(seg.substring(0, markStart - 1));
1257                     Path suffix;
1258                     int markEnd = markStart + MARKER.length();
1259                     if (markEnd == seg.length()) {
1260                         suffix = null;
1261                     } else if (!isSeparator(seg.charAt(markEnd))
1262                             || seg.indexOf(MARKER, markEnd) != -1) {
1263                         throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
1264                     } else {
1265                         suffix = getPath(seg.substring(markEnd + 1));
1266                     }
1267                     add(map, prefix, suffix);
1268                 }
1269             }
1270 
1271             moduleLocations = new LinkedHashMap<>();
1272             pathLocations = new LinkedHashMap<>();
1273             map.forEach((k, v) -> {
1274                 String name = location.getName() + "[" + k + "]";
1275                 ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false, false);
1276                 moduleLocations.put(k, h);
1277                 v.forEach(p -> pathLocations.put(normalize(p), h));
1278             });
1279         }
1280 
1281         private boolean isSeparator(char ch) {
1282             // allow both separators on Windows
1283             return (ch == File.separatorChar) || (ch == '/');
1284         }
1285 
1286         void add(Map<String, Collection<Path>> map, Path prefix, Path suffix) {
1287             if (!Files.isDirectory(prefix)) {
1288                 if (warn) {
1289                     String key = Files.exists(prefix)
1290                             ? "dir.path.element.not.directory"
1291                             : "dir.path.element.not.found";
1292                     log.warning(Lint.LintCategory.PATH, key, prefix);
1293                 }
1294                 return;
1295             }


1395         @Override
1396         Location getLocationForModule(Path dir) {
1397             return (pathLocations == null) ? null : pathLocations.get(dir);
1398         }
1399 
1400         @Override
1401         Iterable<Set<Location>> listLocationsForModules() {
1402             if (moduleLocations == null)
1403                 return Collections.emptySet();
1404             Set<Location> locns = new LinkedHashSet<>();
1405             moduleLocations.forEach((k, v) -> locns.add(v));
1406             return Collections.singleton(locns);
1407         }
1408 
1409     }
1410 
1411     private class SystemModulesLocationHandler extends BasicLocationHandler {
1412         private Path systemJavaHome;
1413         private Path modules;
1414         private Map<String, ModuleLocationHandler> systemModules;

1415 
1416         SystemModulesLocationHandler() {
1417             super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM);
1418             systemJavaHome = Locations.javaHome;
1419         }
1420 
1421         @Override
1422         boolean handleOption(Option option, String value) {
1423             if (!options.contains(option)) {
1424                 return false;
1425             }
1426 
1427             if (value == null) {
1428                 systemJavaHome = Locations.javaHome;
1429             } else if (value.equals("none")) {
1430                 systemJavaHome = null;
1431             } else {
1432                 update(getPath(value));
1433             }
1434 


1469                 throw new IllegalArgumentException(p.toString());
1470             systemJavaHome = p;
1471             modules = null;
1472         }
1473 
1474         private boolean isCurrentPlatform(Path p) {
1475             try {
1476                 return Files.isSameFile(p, Locations.javaHome);
1477             } catch (IOException ex) {
1478                 throw new IllegalArgumentException(p.toString(), ex);
1479             }
1480         }
1481 
1482         @Override
1483         Location getLocationForModule(String name) throws IOException {
1484             initSystemModules();
1485             return systemModules.get(name);
1486         }
1487 
1488         @Override






1489         Iterable<Set<Location>> listLocationsForModules() throws IOException {
1490             initSystemModules();
1491             Set<Location> locns = new LinkedHashSet<>();
1492             for (Location l: systemModules.values())
1493                 locns.add(l);
1494             return Collections.singleton(locns);
1495         }
1496 
1497         private void initSystemModules() throws IOException {
1498             if (systemModules != null) {
1499                 return;
1500             }
1501 
1502             if (systemJavaHome == null) {
1503                 systemModules = Collections.emptyMap();
1504                 return;
1505             }
1506 
1507             if (modules == null) {
1508                 try {


1522                             URLClassLoader fsLoader =
1523                                     new URLClassLoader(new URL[] {javaHomeURL}, currentLoader);
1524 
1525                             jrtfs = FileSystems.newFileSystem(jrtURI, Collections.emptyMap(), fsLoader);
1526 
1527                             closeables.add(fsLoader);
1528                         }
1529 
1530                         closeables.add(jrtfs);
1531                     }
1532 
1533                     modules = jrtfs.getPath("/modules");
1534                 } catch (FileSystemNotFoundException | ProviderNotFoundException e) {
1535                     modules = systemJavaHome.resolve("modules");
1536                     if (!Files.exists(modules))
1537                         throw new IOException("can't find system classes", e);
1538                 }
1539             }
1540 
1541             systemModules = new LinkedHashMap<>();

1542             try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules, Files::isDirectory)) {
1543                 for (Path entry : stream) {
1544                     String moduleName = entry.getFileName().toString();
1545                     String name = location.getName() + "[" + moduleName + "]";
1546                     ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName,
1547                             Collections.singleton(entry), false, true);
1548                     systemModules.put(moduleName, h);


















































1549                 }














1550             }




1551         }









1552     }
1553 
1554     Map<Location, LocationHandler> handlersForLocation;
1555     Map<Option, LocationHandler> handlersForOption;
1556 
1557     void initHandlers() {
1558         handlersForLocation = new HashMap<>();
1559         handlersForOption = new EnumMap<>(Option.class);
1560 
1561         BasicLocationHandler[] handlers = {
1562             new BootClassPathLocationHandler(),
1563             new ClassPathLocationHandler(),
1564             new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCE_PATH),
1565             new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSOR_PATH),
1566             new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSOR_MODULE_PATH),
1567             new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
1568             new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
1569             new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
1570             new ModuleSourcePathLocationHandler(),

1571             // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES?
1572             new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADE_MODULE_PATH),
1573             new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULE_PATH),
1574             new SystemModulesLocationHandler(),
1575         };
1576 
1577         for (BasicLocationHandler h : handlers) {
1578             handlersForLocation.put(h.location, h);
1579             for (Option o : h.options) {
1580                 handlersForOption.put(o, h);
1581             }
1582         }
1583     }
1584 
1585     private Map<String, SearchPath> patchMap;
1586 
1587     boolean handleOption(Option option, String value) {
1588         switch (option) {
1589             case PATCH_MODULE:
1590                 if (value == null) {
1591                     patchMap = null;
1592                 } else {
1593                     // Allow an extended syntax for --patch-module consisting of a series
1594                     // of values separated by NULL characters. This is to facilitate
1595                     // supporting deferred file manager options on the command line.
1596                     // See Option.PATCH_MODULE for the code that composes these multiple
1597                     // values.
1598                     for (String v : value.split("\0")) {
1599                         int eq = v.indexOf('=');
1600                         if (eq > 0) {
1601                             String mName = v.substring(0, eq);
1602                             SearchPath mPatchPath = new SearchPath()
1603                                     .addFiles(v.substring(eq + 1));
1604                             boolean ok = true;
1605                             for (Path p : mPatchPath) {
1606                                 Path mi = p.resolve("module-info.class");
1607                                 if (Files.exists(mi)) {
1608                                     log.error(Errors.LocnModuleInfoNotAllowedOnPatchPath(mi));
1609                                     ok = false;
1610                                 }
1611                             }
1612                             if (ok) {
1613                                 if (patchMap == null) {
1614                                     patchMap = new LinkedHashMap<>();
1615                                 }
1616                                 patchMap.put(mName, mPatchPath);
1617                             }
1618                         } else {
1619                             // Should not be able to get here;
1620                             // this should be caught and handled in Option.PATCH_MODULE
1621                             log.error(Errors.LocnInvalidArgForXpatch(value));
1622                         }
1623                     }
1624                 }
1625                 return true;
1626             default:
1627                 LocationHandler h = handlersForOption.get(option);
1628                 return (h == null ? false : h.handleOption(option, value));
1629         }
1630     }
1631 
1632     boolean hasLocation(Location location) {
1633         LocationHandler h = getHandler(location);
1634         return (h == null ? false : h.isSet());
1635     }
1636 
1637     Collection<Path> getLocation(Location location) {
1638         LocationHandler h = getHandler(location);
1639         return (h == null ? null : h.getPaths());
1640     }
1641 
1642     Path getOutputLocation(Location location) {
1643         if (!location.isOutputLocation()) {
1644             throw new IllegalArgumentException();
1645         }
1646         LocationHandler h = getHandler(location);
1647         return ((OutputLocationHandler) h).outputDir;
1648     }
1649 
1650     void setLocation(Location location, Iterable<? extends Path> files) throws IOException {
1651         LocationHandler h = getHandler(location);
1652         if (h == null) {
1653             if (location.isOutputLocation()) {
1654                 h = new OutputLocationHandler(location);
1655             } else {
1656                 h = new SimpleLocationHandler(location);
1657             }
1658             handlersForLocation.put(location, h);
1659         }
1660         h.setPaths(files);
1661     }
1662 
1663     Location getLocationForModule(Location location, String name) throws IOException {
1664         LocationHandler h = getHandler(location);
1665         return (h == null ? null : h.getLocationForModule(name));
1666     }
1667 
1668     Location getLocationForModule(Location location, Path dir) {
1669         LocationHandler h = getHandler(location);
1670         return (h == null ? null : h.getLocationForModule(dir));
1671     }
1672 
1673     String inferModuleName(Location location) {
1674         LocationHandler h = getHandler(location);
1675         return (h == null ? null : h.inferModuleName());
1676     }
1677 
1678     Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
1679         LocationHandler h = getHandler(location);
1680         return (h == null ? null : h.listLocationsForModules());
1681     }
1682 
1683     protected LocationHandler getHandler(Location location) {
1684         Objects.requireNonNull(location);
1685         return (location instanceof LocationHandler)
1686                 ? (LocationHandler) location
1687                 : handlersForLocation.get(location);
1688     }


 415         /**
 416          * @see StandardJavaFileManager#getLocation
 417          */
 418         abstract Collection<Path> getPaths();
 419 
 420         /**
 421          * @see StandardJavaFileManager#setLocation
 422          */
 423         abstract void setPaths(Iterable<? extends Path> files) throws IOException;
 424 
 425         /**
 426          * @see JavaFileManager#getLocationForModule(Location, String)
 427          */
 428         Location getLocationForModule(String moduleName) throws IOException {
 429             return null;
 430         }
 431 
 432         /**
 433          * @see JavaFileManager#getLocationForModule(Location, JavaFileObject, String)
 434          */
 435         Location getLocationForModule(Path dir) throws IOException  {
 436             return null;
 437         }
 438 
 439         /**
 440          * @see JavaFileManager#inferModuleName
 441          */
 442         String inferModuleName() {
 443             return null;
 444         }
 445 
 446         /**
 447          * @see JavaFileManager#listLocationsForModules
 448          */
 449         Iterable<Set<Location>> listLocationsForModules() throws IOException {
 450             return null;
 451         }
 452     }
 453 
 454     /**
 455      * A LocationHandler for a given Location, and associated set of options.


 528                     throw new IOException(dir + ": not a directory");
 529                 }
 530                 outputDir = dir;
 531             }
 532             moduleLocations = null;
 533             pathLocations = null;
 534         }
 535 
 536         @Override
 537         Location getLocationForModule(String name) {
 538             if (moduleLocations == null) {
 539                 moduleLocations = new HashMap<>();
 540                 pathLocations = new HashMap<>();
 541             }
 542             Location l = moduleLocations.get(name);
 543             if (l == null) {
 544                 Path out = outputDir.resolve(name);
 545                 l = new ModuleLocationHandler(location.getName() + "[" + name + "]",
 546                         name,
 547                         Collections.singleton(out),
 548                         true);
 549                 moduleLocations.put(name, l);
 550                 pathLocations.put(out.toAbsolutePath(), l);
 551            }
 552             return l;
 553         }
 554 
 555         @Override
 556         Location getLocationForModule(Path dir) {
 557             return (pathLocations == null) ? null : pathLocations.get(dir);
 558         }
 559 
 560         private boolean listed;
 561 
 562         @Override
 563         Iterable<Set<Location>> listLocationsForModules() throws IOException {
 564             if (!listed && outputDir != null) {
 565                 try (DirectoryStream<Path> stream = Files.newDirectoryStream(outputDir)) {
 566                     for (Path p : stream) {
 567                         getLocationForModule(p.getFileName().toString());
 568                     }


 847                 } catch (IOException e) {
 848                     // TODO: need better handling here, e.g. javac Abort?
 849                     throw new UncheckedIOException(e);
 850                 }
 851             }
 852         }
 853     }
 854 
 855     /**
 856      * A LocationHander to represent modules found from a module-oriented
 857      * location such as MODULE_SOURCE_PATH, UPGRADE_MODULE_PATH,
 858      * SYSTEM_MODULES and MODULE_PATH.
 859      *
 860      * The Location can be specified to accept overriding classes from the
 861      * {@code --patch-module <module>=<path> } parameter.
 862      */
 863     private class ModuleLocationHandler extends LocationHandler implements Location {
 864         protected final String name;
 865         protected final String moduleName;
 866         protected final Collection<Path> searchPath;

 867         protected final boolean output;
 868 
 869         ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath,
 870                 boolean output) {
 871             this.name = name;
 872             this.moduleName = moduleName;
 873             this.searchPath = searchPath;
 874             this.output = output;














 875         }
 876 
 877         @Override @DefinedBy(Api.COMPILER)
 878         public String getName() {
 879             return name;
 880         }
 881 
 882         @Override @DefinedBy(Api.COMPILER)
 883         public boolean isOutputLocation() {
 884             return output;
 885         }
 886 
 887         @Override // defined by LocationHandler
 888         boolean handleOption(Option option, String value) {
 889             throw new UnsupportedOperationException();
 890         }
 891 
 892         @Override // defined by LocationHandler
 893         Collection<Path> getPaths() {
 894             // For now, we always return searchPathWithOverrides. This may differ from the
 895             // JVM behavior if there is a module-info.class to be found in the overriding
 896             // classes.
 897             return searchPath;
 898         }
 899 
 900         @Override // defined by LocationHandler
 901         void setPaths(Iterable<? extends Path> files) throws IOException {
 902             throw new UnsupportedOperationException();
 903         }
 904 
 905         @Override // defined by LocationHandler
 906         String inferModuleName() {
 907             return moduleName;
 908         }
 909     }
 910 
 911     /**
 912      * A LocationHandler for simple module-oriented search paths,
 913      * like UPGRADE_MODULE_PATH and MODULE_PATH.
 914      */
 915     private class ModulePathLocationHandler extends SimpleLocationHandler {
 916         private Map<String, ModuleLocationHandler> pathModules;
 917 


1031                         if (entry.endsWith("module-info.class")) {
1032                             moduleInfoClass = entry;
1033                             break;  // no need to continue scanning
1034                         }
1035                         paths.add(entry);
1036                     }
1037                 } catch (DirectoryIteratorException | IOException ignore) {
1038                     log.error(Errors.LocnCantReadDirectory(path));
1039                     return Collections.emptySet();
1040                 }
1041 
1042                 if (moduleInfoClass != null) {
1043                     // It's an exploded module directly on the module path.
1044                     // We can't infer module name from the directory name, so have to
1045                     // read module-info.class.
1046                     try {
1047                         String moduleName = readModuleName(moduleInfoClass);
1048                         String name = location.getName()
1049                                 + "[" + pathIndex + ":" + moduleName + "]";
1050                         ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
1051                                 Collections.singleton(path), false);
1052                         return Collections.singleton(l);
1053                     } catch (ModuleNameReader.BadClassFile e) {
1054                         log.error(Errors.LocnBadModuleInfo(path));
1055                         return Collections.emptySet();
1056                     } catch (IOException e) {
1057                         log.error(Errors.LocnCantReadFile(path));
1058                         return Collections.emptySet();
1059                     }
1060                 }
1061 
1062                 // A directory of modules
1063                 Set<Location> result = new LinkedHashSet<>();
1064                 int index = 0;
1065                 for (Path entry : paths) {
1066                     Pair<String,Path> module = inferModuleName(entry);
1067                     if (module == null) {
1068                         // diagnostic reported if necessary; skip to next
1069                         continue;
1070                     }
1071                     String moduleName = module.fst;
1072                     Path modulePath = module.snd;
1073                     String name = location.getName()
1074                             + "[" + pathIndex + "." + (index++) + ":" + moduleName + "]";
1075                     ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
1076                             Collections.singleton(modulePath), false);
1077                     result.add(l);
1078                 }
1079                 return result;
1080             }
1081 
1082             private Set<Location> scanFile(Path path) {
1083                 Pair<String,Path> module = inferModuleName(path);
1084                 if (module == null) {
1085                     // diagnostic reported if necessary
1086                     return Collections.emptySet();
1087                 }
1088                 String moduleName = module.fst;
1089                 Path modulePath = module.snd;
1090                 String name = location.getName()
1091                         + "[" + pathIndex + ":" + moduleName + "]";
1092                 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
1093                         Collections.singleton(modulePath), false);
1094                 return Collections.singleton(l);
1095             }
1096 
1097             private Pair<String,Path> inferModuleName(Path p) {
1098                 if (Files.isDirectory(p)) {
1099                     if (Files.exists(p.resolve("module-info.class"))) {
1100                         String name = p.getFileName().toString();
1101                         if (SourceVersion.isName(name))
1102                             return new Pair<>(name, p);
1103                     }
1104                     return null;
1105                 }
1106 
1107                 if (p.getFileName().toString().endsWith(".jar") && fsInfo.exists(p)) {
1108                     FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider();
1109                     if (jarFSProvider == null) {
1110                         log.error(Errors.NoZipfsForArchive(p));
1111                         return null;
1112                     }
1113                     try (FileSystem fs = jarFSProvider.newFileSystem(p, fsEnv)) {


1240                     }
1241                     Path prefix = getPath(seg.substring(0, markStart - 1));
1242                     Path suffix;
1243                     int markEnd = markStart + MARKER.length();
1244                     if (markEnd == seg.length()) {
1245                         suffix = null;
1246                     } else if (!isSeparator(seg.charAt(markEnd))
1247                             || seg.indexOf(MARKER, markEnd) != -1) {
1248                         throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
1249                     } else {
1250                         suffix = getPath(seg.substring(markEnd + 1));
1251                     }
1252                     add(map, prefix, suffix);
1253                 }
1254             }
1255 
1256             moduleLocations = new LinkedHashMap<>();
1257             pathLocations = new LinkedHashMap<>();
1258             map.forEach((k, v) -> {
1259                 String name = location.getName() + "[" + k + "]";
1260                 ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false);
1261                 moduleLocations.put(k, h);
1262                 v.forEach(p -> pathLocations.put(normalize(p), h));
1263             });
1264         }
1265 
1266         private boolean isSeparator(char ch) {
1267             // allow both separators on Windows
1268             return (ch == File.separatorChar) || (ch == '/');
1269         }
1270 
1271         void add(Map<String, Collection<Path>> map, Path prefix, Path suffix) {
1272             if (!Files.isDirectory(prefix)) {
1273                 if (warn) {
1274                     String key = Files.exists(prefix)
1275                             ? "dir.path.element.not.directory"
1276                             : "dir.path.element.not.found";
1277                     log.warning(Lint.LintCategory.PATH, key, prefix);
1278                 }
1279                 return;
1280             }


1380         @Override
1381         Location getLocationForModule(Path dir) {
1382             return (pathLocations == null) ? null : pathLocations.get(dir);
1383         }
1384 
1385         @Override
1386         Iterable<Set<Location>> listLocationsForModules() {
1387             if (moduleLocations == null)
1388                 return Collections.emptySet();
1389             Set<Location> locns = new LinkedHashSet<>();
1390             moduleLocations.forEach((k, v) -> locns.add(v));
1391             return Collections.singleton(locns);
1392         }
1393 
1394     }
1395 
1396     private class SystemModulesLocationHandler extends BasicLocationHandler {
1397         private Path systemJavaHome;
1398         private Path modules;
1399         private Map<String, ModuleLocationHandler> systemModules;
1400         private Map<Path, Location> pathLocations;
1401 
1402         SystemModulesLocationHandler() {
1403             super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM);
1404             systemJavaHome = Locations.javaHome;
1405         }
1406 
1407         @Override
1408         boolean handleOption(Option option, String value) {
1409             if (!options.contains(option)) {
1410                 return false;
1411             }
1412 
1413             if (value == null) {
1414                 systemJavaHome = Locations.javaHome;
1415             } else if (value.equals("none")) {
1416                 systemJavaHome = null;
1417             } else {
1418                 update(getPath(value));
1419             }
1420 


1455                 throw new IllegalArgumentException(p.toString());
1456             systemJavaHome = p;
1457             modules = null;
1458         }
1459 
1460         private boolean isCurrentPlatform(Path p) {
1461             try {
1462                 return Files.isSameFile(p, Locations.javaHome);
1463             } catch (IOException ex) {
1464                 throw new IllegalArgumentException(p.toString(), ex);
1465             }
1466         }
1467 
1468         @Override
1469         Location getLocationForModule(String name) throws IOException {
1470             initSystemModules();
1471             return systemModules.get(name);
1472         }
1473 
1474         @Override
1475         Location getLocationForModule(Path dir) throws IOException {
1476             initSystemModules();
1477             return (pathLocations == null) ? null : pathLocations.get(dir);
1478         }
1479 
1480         @Override
1481         Iterable<Set<Location>> listLocationsForModules() throws IOException {
1482             initSystemModules();
1483             Set<Location> locns = new LinkedHashSet<>();
1484             for (Location l: systemModules.values())
1485                 locns.add(l);
1486             return Collections.singleton(locns);
1487         }
1488 
1489         private void initSystemModules() throws IOException {
1490             if (systemModules != null) {
1491                 return;
1492             }
1493 
1494             if (systemJavaHome == null) {
1495                 systemModules = Collections.emptyMap();
1496                 return;
1497             }
1498 
1499             if (modules == null) {
1500                 try {


1514                             URLClassLoader fsLoader =
1515                                     new URLClassLoader(new URL[] {javaHomeURL}, currentLoader);
1516 
1517                             jrtfs = FileSystems.newFileSystem(jrtURI, Collections.emptyMap(), fsLoader);
1518 
1519                             closeables.add(fsLoader);
1520                         }
1521 
1522                         closeables.add(jrtfs);
1523                     }
1524 
1525                     modules = jrtfs.getPath("/modules");
1526                 } catch (FileSystemNotFoundException | ProviderNotFoundException e) {
1527                     modules = systemJavaHome.resolve("modules");
1528                     if (!Files.exists(modules))
1529                         throw new IOException("can't find system classes", e);
1530                 }
1531             }
1532 
1533             systemModules = new LinkedHashMap<>();
1534             pathLocations = new LinkedHashMap<>();
1535             try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules, Files::isDirectory)) {
1536                 for (Path entry : stream) {
1537                     String moduleName = entry.getFileName().toString();
1538                     String name = location.getName() + "[" + moduleName + "]";
1539                     ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName,
1540                             Collections.singleton(entry), false);
1541                     systemModules.put(moduleName, h);
1542                     pathLocations.put(normalize(entry), h);
1543                 }
1544             }
1545         }
1546     }
1547 
1548     private class PatchModulesLocationHandler extends BasicLocationHandler {
1549         private final Map<String, ModuleLocationHandler> moduleLocations = new HashMap<>();
1550         private final Map<Path, Location> pathLocations = new HashMap<>();
1551 
1552         PatchModulesLocationHandler() {
1553             super(StandardLocation.PATCH_MODULE_PATH, Option.PATCH_MODULE);
1554         }
1555 
1556         @Override
1557         boolean handleOption(Option option, String value) {
1558             if (!options.contains(option)) {
1559                 return false;
1560             }
1561 
1562             // Allow an extended syntax for --patch-module consisting of a series
1563             // of values separated by NULL characters. This is to facilitate
1564             // supporting deferred file manager options on the command line.
1565             // See Option.PATCH_MODULE for the code that composes these multiple
1566             // values.
1567             for (String v : value.split("\0")) {
1568                 int eq = v.indexOf('=');
1569                 if (eq > 0) {
1570                     String moduleName = v.substring(0, eq);
1571                     SearchPath mPatchPath = new SearchPath()
1572                             .addFiles(v.substring(eq + 1));
1573                     String name = location.getName() + "[" + moduleName + "]";
1574                     ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName, mPatchPath, false);
1575                     moduleLocations.put(moduleName, h);
1576                     for (Path r : mPatchPath) {
1577                         pathLocations.put(normalize(r), h);
1578                     }
1579                 } else {
1580                     // Should not be able to get here;
1581                     // this should be caught and handled in Option.PATCH_MODULE
1582                     log.error(Errors.LocnInvalidArgForXpatch(value));
1583                 }
1584             }
1585 
1586             return true;
1587         }
1588 
1589         @Override
1590         boolean isSet() {
1591             return !moduleLocations.isEmpty();
1592         }
1593 
1594         @Override
1595         Collection<Path> getPaths() {
1596             throw new UnsupportedOperationException();
1597         }
1598 
1599         @Override
1600         void setPaths(Iterable<? extends Path> files) throws IOException {
1601             throw new UnsupportedOperationException();
1602         }
1603 
1604         @Override
1605         Location getLocationForModule(String name) throws IOException {
1606             return moduleLocations.get(name);
1607         }
1608 
1609         @Override
1610         Location getLocationForModule(Path dir) throws IOException {
1611             return (pathLocations == null) ? null : pathLocations.get(dir);
1612         }
1613 
1614         @Override
1615         Iterable<Set<Location>> listLocationsForModules() throws IOException {
1616             Set<Location> locns = new LinkedHashSet<>();
1617             for (Location l: moduleLocations.values())
1618                 locns.add(l);
1619             return Collections.singleton(locns);
1620         }
1621 
1622     }
1623 
1624     Map<Location, LocationHandler> handlersForLocation;
1625     Map<Option, LocationHandler> handlersForOption;
1626 
1627     void initHandlers() {
1628         handlersForLocation = new HashMap<>();
1629         handlersForOption = new EnumMap<>(Option.class);
1630 
1631         BasicLocationHandler[] handlers = {
1632             new BootClassPathLocationHandler(),
1633             new ClassPathLocationHandler(),
1634             new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCE_PATH),
1635             new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSOR_PATH),
1636             new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSOR_MODULE_PATH),
1637             new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
1638             new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
1639             new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
1640             new ModuleSourcePathLocationHandler(),
1641             new PatchModulesLocationHandler(),
1642             // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES?
1643             new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADE_MODULE_PATH),
1644             new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULE_PATH),
1645             new SystemModulesLocationHandler(),
1646         };
1647 
1648         for (BasicLocationHandler h : handlers) {
1649             handlersForLocation.put(h.location, h);
1650             for (Option o : h.options) {
1651                 handlersForOption.put(o, h);
1652             }
1653         }
1654     }
1655 


1656     boolean handleOption(Option option, String value) {







































1657         LocationHandler h = handlersForOption.get(option);
1658         return (h == null ? false : h.handleOption(option, value));
1659     }

1660 
1661     boolean hasLocation(Location location) {
1662         LocationHandler h = getHandler(location);
1663         return (h == null ? false : h.isSet());
1664     }
1665 
1666     Collection<Path> getLocation(Location location) {
1667         LocationHandler h = getHandler(location);
1668         return (h == null ? null : h.getPaths());
1669     }
1670 
1671     Path getOutputLocation(Location location) {
1672         if (!location.isOutputLocation()) {
1673             throw new IllegalArgumentException();
1674         }
1675         LocationHandler h = getHandler(location);
1676         return ((OutputLocationHandler) h).outputDir;
1677     }
1678 
1679     void setLocation(Location location, Iterable<? extends Path> files) throws IOException {
1680         LocationHandler h = getHandler(location);
1681         if (h == null) {
1682             if (location.isOutputLocation()) {
1683                 h = new OutputLocationHandler(location);
1684             } else {
1685                 h = new SimpleLocationHandler(location);
1686             }
1687             handlersForLocation.put(location, h);
1688         }
1689         h.setPaths(files);
1690     }
1691 
1692     Location getLocationForModule(Location location, String name) throws IOException {
1693         LocationHandler h = getHandler(location);
1694         return (h == null ? null : h.getLocationForModule(name));
1695     }
1696 
1697     Location getLocationForModule(Location location, Path dir) throws IOException {
1698         LocationHandler h = getHandler(location);
1699         return (h == null ? null : h.getLocationForModule(dir));
1700     }
1701 
1702     String inferModuleName(Location location) {
1703         LocationHandler h = getHandler(location);
1704         return (h == null ? null : h.inferModuleName());
1705     }
1706 
1707     Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
1708         LocationHandler h = getHandler(location);
1709         return (h == null ? null : h.listLocationsForModules());
1710     }
1711 
1712     protected LocationHandler getHandler(Location location) {
1713         Objects.requireNonNull(location);
1714         return (location instanceof LocationHandler)
1715                 ? (LocationHandler) location
1716                 : handlersForLocation.get(location);
1717     }
< prev index next >