862 */ |
862 */ |
863 private class ModuleLocationHandler extends LocationHandler implements Location { |
863 private class ModuleLocationHandler extends LocationHandler implements Location { |
864 protected final String name; |
864 protected final String name; |
865 protected final String moduleName; |
865 protected final String moduleName; |
866 protected final Collection<Path> searchPath; |
866 protected final Collection<Path> searchPath; |
867 protected final Collection<Path> searchPathWithOverrides; |
|
868 protected final boolean output; |
867 protected final boolean output; |
869 |
868 |
870 ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath, |
869 ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath, |
871 boolean output, boolean allowOverrides) { |
870 boolean output) { |
872 this.name = name; |
871 this.name = name; |
873 this.moduleName = moduleName; |
872 this.moduleName = moduleName; |
874 this.searchPath = searchPath; |
873 this.searchPath = searchPath; |
875 this.output = output; |
874 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 } |
875 } |
891 |
876 |
892 @Override @DefinedBy(Api.COMPILER) |
877 @Override @DefinedBy(Api.COMPILER) |
893 public String getName() { |
878 public String getName() { |
894 return name; |
879 return name; |
907 @Override // defined by LocationHandler |
892 @Override // defined by LocationHandler |
908 Collection<Path> getPaths() { |
893 Collection<Path> getPaths() { |
909 // For now, we always return searchPathWithOverrides. This may differ from the |
894 // 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 |
895 // JVM behavior if there is a module-info.class to be found in the overriding |
911 // classes. |
896 // classes. |
912 return searchPathWithOverrides; |
897 return searchPath; |
913 } |
898 } |
914 |
899 |
915 @Override // defined by LocationHandler |
900 @Override // defined by LocationHandler |
916 void setPaths(Iterable<? extends Path> files) throws IOException { |
901 void setPaths(Iterable<? extends Path> files) throws IOException { |
917 throw new UnsupportedOperationException(); |
902 throw new UnsupportedOperationException(); |
1066 try { |
1051 try { |
1067 String moduleName = readModuleName(moduleInfoClass); |
1052 String moduleName = readModuleName(moduleInfoClass); |
1068 String name = location.getName() |
1053 String name = location.getName() |
1069 + "[" + pathIndex + ":" + moduleName + "]"; |
1054 + "[" + pathIndex + ":" + moduleName + "]"; |
1070 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName, |
1055 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName, |
1071 Collections.singleton(path), false, true); |
1056 Collections.singleton(path), false); |
1072 return Collections.singleton(l); |
1057 return Collections.singleton(l); |
1073 } catch (ModuleNameReader.BadClassFile e) { |
1058 } catch (ModuleNameReader.BadClassFile e) { |
1074 log.error(Errors.LocnBadModuleInfo(path)); |
1059 log.error(Errors.LocnBadModuleInfo(path)); |
1075 return Collections.emptySet(); |
1060 return Collections.emptySet(); |
1076 } catch (IOException e) { |
1061 } catch (IOException e) { |
1091 String moduleName = module.fst; |
1076 String moduleName = module.fst; |
1092 Path modulePath = module.snd; |
1077 Path modulePath = module.snd; |
1093 String name = location.getName() |
1078 String name = location.getName() |
1094 + "[" + pathIndex + "." + (index++) + ":" + moduleName + "]"; |
1079 + "[" + pathIndex + "." + (index++) + ":" + moduleName + "]"; |
1095 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName, |
1080 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName, |
1096 Collections.singleton(modulePath), false, true); |
1081 Collections.singleton(modulePath), false); |
1097 result.add(l); |
1082 result.add(l); |
1098 } |
1083 } |
1099 return result; |
1084 return result; |
1100 } |
1085 } |
1101 |
1086 |
1108 String moduleName = module.fst; |
1093 String moduleName = module.fst; |
1109 Path modulePath = module.snd; |
1094 Path modulePath = module.snd; |
1110 String name = location.getName() |
1095 String name = location.getName() |
1111 + "[" + pathIndex + ":" + moduleName + "]"; |
1096 + "[" + pathIndex + ":" + moduleName + "]"; |
1112 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName, |
1097 ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName, |
1113 Collections.singleton(modulePath), false, true); |
1098 Collections.singleton(modulePath), false); |
1114 return Collections.singleton(l); |
1099 return Collections.singleton(l); |
1115 } |
1100 } |
1116 |
1101 |
1117 private Pair<String,Path> inferModuleName(Path p) { |
1102 private Pair<String,Path> inferModuleName(Path p) { |
1118 if (Files.isDirectory(p)) { |
1103 if (Files.isDirectory(p)) { |
1275 |
1260 |
1276 moduleLocations = new LinkedHashMap<>(); |
1261 moduleLocations = new LinkedHashMap<>(); |
1277 pathLocations = new LinkedHashMap<>(); |
1262 pathLocations = new LinkedHashMap<>(); |
1278 map.forEach((k, v) -> { |
1263 map.forEach((k, v) -> { |
1279 String name = location.getName() + "[" + k + "]"; |
1264 String name = location.getName() + "[" + k + "]"; |
1280 ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false, false); |
1265 ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false); |
1281 moduleLocations.put(k, h); |
1266 moduleLocations.put(k, h); |
1282 v.forEach(p -> pathLocations.put(normalize(p), h)); |
1267 v.forEach(p -> pathLocations.put(normalize(p), h)); |
1283 }); |
1268 }); |
1284 } |
1269 } |
1285 |
1270 |
1415 |
1400 |
1416 private class SystemModulesLocationHandler extends BasicLocationHandler { |
1401 private class SystemModulesLocationHandler extends BasicLocationHandler { |
1417 private Path systemJavaHome; |
1402 private Path systemJavaHome; |
1418 private Path modules; |
1403 private Path modules; |
1419 private Map<String, ModuleLocationHandler> systemModules; |
1404 private Map<String, ModuleLocationHandler> systemModules; |
|
1405 private Map<Path, Location> pathLocations; |
1420 |
1406 |
1421 SystemModulesLocationHandler() { |
1407 SystemModulesLocationHandler() { |
1422 super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM); |
1408 super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM); |
1423 systemJavaHome = Locations.javaHome; |
1409 systemJavaHome = Locations.javaHome; |
1424 } |
1410 } |
1542 throw new IOException("can't find system classes", e); |
1534 throw new IOException("can't find system classes", e); |
1543 } |
1535 } |
1544 } |
1536 } |
1545 |
1537 |
1546 systemModules = new LinkedHashMap<>(); |
1538 systemModules = new LinkedHashMap<>(); |
|
1539 pathLocations = new LinkedHashMap<>(); |
1547 try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules, Files::isDirectory)) { |
1540 try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules, Files::isDirectory)) { |
1548 for (Path entry : stream) { |
1541 for (Path entry : stream) { |
1549 String moduleName = entry.getFileName().toString(); |
1542 String moduleName = entry.getFileName().toString(); |
1550 String name = location.getName() + "[" + moduleName + "]"; |
1543 String name = location.getName() + "[" + moduleName + "]"; |
1551 ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName, |
1544 ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName, |
1552 Collections.singleton(entry), false, true); |
1545 Collections.singleton(entry), false); |
1553 systemModules.put(moduleName, h); |
1546 systemModules.put(moduleName, h); |
1554 } |
1547 pathLocations.put(normalize(entry), h); |
1555 } |
1548 } |
1556 } |
1549 } |
|
1550 } |
|
1551 } |
|
1552 |
|
1553 private class PatchModulesLocationHandler extends BasicLocationHandler { |
|
1554 private final Map<String, ModuleLocationHandler> moduleLocations = new HashMap<>(); |
|
1555 private final Map<Path, Location> pathLocations = new HashMap<>(); |
|
1556 |
|
1557 PatchModulesLocationHandler() { |
|
1558 super(StandardLocation.PATCH_MODULE_PATH, Option.PATCH_MODULE); |
|
1559 } |
|
1560 |
|
1561 @Override |
|
1562 boolean handleOption(Option option, String value) { |
|
1563 if (!options.contains(option)) { |
|
1564 return false; |
|
1565 } |
|
1566 |
|
1567 // Allow an extended syntax for --patch-module consisting of a series |
|
1568 // of values separated by NULL characters. This is to facilitate |
|
1569 // supporting deferred file manager options on the command line. |
|
1570 // See Option.PATCH_MODULE for the code that composes these multiple |
|
1571 // values. |
|
1572 for (String v : value.split("\0")) { |
|
1573 int eq = v.indexOf('='); |
|
1574 if (eq > 0) { |
|
1575 String moduleName = v.substring(0, eq); |
|
1576 SearchPath mPatchPath = new SearchPath() |
|
1577 .addFiles(v.substring(eq + 1)); |
|
1578 String name = location.getName() + "[" + moduleName + "]"; |
|
1579 ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName, mPatchPath, false); |
|
1580 moduleLocations.put(moduleName, h); |
|
1581 for (Path r : mPatchPath) { |
|
1582 pathLocations.put(normalize(r), h); |
|
1583 } |
|
1584 } else { |
|
1585 // Should not be able to get here; |
|
1586 // this should be caught and handled in Option.PATCH_MODULE |
|
1587 log.error(Errors.LocnInvalidArgForXpatch(value)); |
|
1588 } |
|
1589 } |
|
1590 |
|
1591 return true; |
|
1592 } |
|
1593 |
|
1594 @Override |
|
1595 boolean isSet() { |
|
1596 return !moduleLocations.isEmpty(); |
|
1597 } |
|
1598 |
|
1599 @Override |
|
1600 Collection<Path> getPaths() { |
|
1601 throw new UnsupportedOperationException(); |
|
1602 } |
|
1603 |
|
1604 @Override |
|
1605 void setPaths(Iterable<? extends Path> files) throws IOException { |
|
1606 throw new UnsupportedOperationException(); |
|
1607 } |
|
1608 |
|
1609 @Override |
|
1610 Location getLocationForModule(String name) throws IOException { |
|
1611 return moduleLocations.get(name); |
|
1612 } |
|
1613 |
|
1614 @Override |
|
1615 Location getLocationForModule(Path dir) throws IOException { |
|
1616 return (pathLocations == null) ? null : pathLocations.get(dir); |
|
1617 } |
|
1618 |
|
1619 @Override |
|
1620 Iterable<Set<Location>> listLocationsForModules() throws IOException { |
|
1621 Set<Location> locns = new LinkedHashSet<>(); |
|
1622 for (Location l: moduleLocations.values()) |
|
1623 locns.add(l); |
|
1624 return Collections.singleton(locns); |
|
1625 } |
|
1626 |
1557 } |
1627 } |
1558 |
1628 |
1559 Map<Location, LocationHandler> handlersForLocation; |
1629 Map<Location, LocationHandler> handlersForLocation; |
1560 Map<Option, LocationHandler> handlersForOption; |
1630 Map<Option, LocationHandler> handlersForOption; |
1561 |
1631 |
1571 new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSOR_MODULE_PATH), |
1641 new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSOR_MODULE_PATH), |
1572 new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D), |
1642 new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D), |
1573 new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S), |
1643 new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S), |
1574 new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H), |
1644 new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H), |
1575 new ModuleSourcePathLocationHandler(), |
1645 new ModuleSourcePathLocationHandler(), |
|
1646 new PatchModulesLocationHandler(), |
1576 // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES? |
1647 // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES? |
1577 new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADE_MODULE_PATH), |
1648 new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADE_MODULE_PATH), |
1578 new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULE_PATH), |
1649 new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULE_PATH), |
1579 new SystemModulesLocationHandler(), |
1650 new SystemModulesLocationHandler(), |
1580 }; |
1651 }; |
1585 handlersForOption.put(o, h); |
1656 handlersForOption.put(o, h); |
1586 } |
1657 } |
1587 } |
1658 } |
1588 } |
1659 } |
1589 |
1660 |
1590 private Map<String, SearchPath> patchMap; |
|
1591 |
|
1592 boolean handleOption(Option option, String value) { |
1661 boolean handleOption(Option option, String value) { |
1593 switch (option) { |
1662 LocationHandler h = handlersForOption.get(option); |
1594 case PATCH_MODULE: |
1663 return (h == null ? false : h.handleOption(option, value)); |
1595 if (value == null) { |
|
1596 patchMap = null; |
|
1597 } else { |
|
1598 // Allow an extended syntax for --patch-module consisting of a series |
|
1599 // of values separated by NULL characters. This is to facilitate |
|
1600 // supporting deferred file manager options on the command line. |
|
1601 // See Option.PATCH_MODULE for the code that composes these multiple |
|
1602 // values. |
|
1603 for (String v : value.split("\0")) { |
|
1604 int eq = v.indexOf('='); |
|
1605 if (eq > 0) { |
|
1606 String mName = v.substring(0, eq); |
|
1607 SearchPath mPatchPath = new SearchPath() |
|
1608 .addFiles(v.substring(eq + 1)); |
|
1609 boolean ok = true; |
|
1610 for (Path p : mPatchPath) { |
|
1611 Path mi = p.resolve("module-info.class"); |
|
1612 if (Files.exists(mi)) { |
|
1613 log.error(Errors.LocnModuleInfoNotAllowedOnPatchPath(mi)); |
|
1614 ok = false; |
|
1615 } |
|
1616 } |
|
1617 if (ok) { |
|
1618 if (patchMap == null) { |
|
1619 patchMap = new LinkedHashMap<>(); |
|
1620 } |
|
1621 patchMap.put(mName, mPatchPath); |
|
1622 } |
|
1623 } else { |
|
1624 // Should not be able to get here; |
|
1625 // this should be caught and handled in Option.PATCH_MODULE |
|
1626 log.error(Errors.LocnInvalidArgForXpatch(value)); |
|
1627 } |
|
1628 } |
|
1629 } |
|
1630 return true; |
|
1631 default: |
|
1632 LocationHandler h = handlersForOption.get(option); |
|
1633 return (h == null ? false : h.handleOption(option, value)); |
|
1634 } |
|
1635 } |
1664 } |
1636 |
1665 |
1637 boolean hasLocation(Location location) { |
1666 boolean hasLocation(Location location) { |
1638 LocationHandler h = getHandler(location); |
1667 LocationHandler h = getHandler(location); |
1639 return (h == null ? false : h.isSet()); |
1668 return (h == null ? false : h.isSet()); |
1668 Location getLocationForModule(Location location, String name) throws IOException { |
1697 Location getLocationForModule(Location location, String name) throws IOException { |
1669 LocationHandler h = getHandler(location); |
1698 LocationHandler h = getHandler(location); |
1670 return (h == null ? null : h.getLocationForModule(name)); |
1699 return (h == null ? null : h.getLocationForModule(name)); |
1671 } |
1700 } |
1672 |
1701 |
1673 Location getLocationForModule(Location location, Path dir) { |
1702 Location getLocationForModule(Location location, Path dir) throws IOException { |
1674 LocationHandler h = getHandler(location); |
1703 LocationHandler h = getHandler(location); |
1675 return (h == null ? null : h.getLocationForModule(dir)); |
1704 return (h == null ? null : h.getLocationForModule(dir)); |
1676 } |
1705 } |
1677 |
1706 |
1678 String inferModuleName(Location location) { |
1707 String inferModuleName(Location location) { |