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 }
|