67 import javax.lang.model.SourceVersion;
68 import javax.tools.JavaFileManager;
69 import javax.tools.JavaFileManager.Location;
70 import javax.tools.StandardJavaFileManager;
71 import javax.tools.StandardJavaFileManager.PathFactory;
72 import javax.tools.StandardLocation;
73
74 import com.sun.tools.javac.code.Lint;
75 import com.sun.tools.javac.main.Option;
76 import com.sun.tools.javac.resources.CompilerProperties.Errors;
77 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
78 import com.sun.tools.javac.util.DefinedBy;
79 import com.sun.tools.javac.util.DefinedBy.Api;
80 import com.sun.tools.javac.util.ListBuffer;
81 import com.sun.tools.javac.util.Log;
82 import com.sun.tools.javac.util.Pair;
83 import com.sun.tools.javac.util.StringUtils;
84
85 import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
86
87 import static com.sun.tools.javac.main.Option.BOOTCLASSPATH;
88 import static com.sun.tools.javac.main.Option.DJAVA_ENDORSED_DIRS;
89 import static com.sun.tools.javac.main.Option.DJAVA_EXT_DIRS;
90 import static com.sun.tools.javac.main.Option.ENDORSEDDIRS;
91 import static com.sun.tools.javac.main.Option.EXTDIRS;
92 import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH;
93 import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_APPEND;
94 import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_PREPEND;
95
96 /**
97 * This class converts command line arguments, environment variables and system properties (in
98 * File.pathSeparator-separated String form) into a boot class path, user class path, and source
99 * path (in {@code Collection<String>} form).
100 *
101 * <p>
102 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
103 * your own risk. This code and its internal interfaces are subject to change or deletion without
104 * notice.</b>
105 */
106 public class Locations {
107
563 }
564 searchPath = Collections.unmodifiableCollection(p);
565 }
566
567 protected SearchPath computePath(String value) {
568 return createPath().addFiles(value);
569 }
570
571 protected SearchPath createPath() {
572 return new SearchPath();
573 }
574 }
575
576 /**
577 * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
578 * If no value is given, a default is provided, based on system properties and other values.
579 */
580 private class ClassPathLocationHandler extends SimpleLocationHandler {
581
582 ClassPathLocationHandler() {
583 super(StandardLocation.CLASS_PATH,
584 Option.CLASSPATH, Option.CP);
585 }
586
587 @Override
588 Collection<Path> getPaths() {
589 lazy();
590 return searchPath;
591 }
592
593 @Override
594 protected SearchPath computePath(String value) {
595 String cp = value;
596
597 // CLASSPATH environment variable when run from `javac'.
598 if (cp == null) {
599 cp = System.getProperty("env.class.path");
600 }
601
602 // If invoked via a java VM (not the javac launcher), use the
603 // platform class path
604 if (cp == null && System.getProperty("application.home") == null) {
632 * Various options are supported for different components of the
633 * platform class path.
634 * Setting a value with setLocation overrides all existing option values.
635 * Setting any option overrides any value set with setLocation, and
636 * reverts to using default values for options that have not been set.
637 * Setting -bootclasspath or -Xbootclasspath overrides any existing
638 * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
639 */
640 private class BootClassPathLocationHandler extends BasicLocationHandler {
641
642 private Collection<Path> searchPath;
643 final Map<Option, String> optionValues = new EnumMap<>(Option.class);
644
645 /**
646 * Is the bootclasspath the default?
647 */
648 private boolean isDefault;
649
650 BootClassPathLocationHandler() {
651 super(StandardLocation.PLATFORM_CLASS_PATH,
652 Option.BOOTCLASSPATH, Option.XBOOTCLASSPATH,
653 Option.XBOOTCLASSPATH_PREPEND,
654 Option.XBOOTCLASSPATH_APPEND,
655 Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
656 Option.EXTDIRS, Option.DJAVA_EXT_DIRS);
657 }
658
659 boolean isDefault() {
660 lazy();
661 return isDefault;
662 }
663
664 @Override
665 boolean handleOption(Option option, String value) {
666 if (!options.contains(option)) {
667 return false;
668 }
669
670 option = canonicalize(option);
671 optionValues.put(option, value);
672 if (option == BOOTCLASSPATH) {
673 optionValues.remove(XBOOTCLASSPATH_PREPEND);
674 optionValues.remove(XBOOTCLASSPATH_APPEND);
675 }
676 searchPath = null; // reset to "uninitialized"
677 return true;
678 }
679 // where
680 // TODO: would be better if option aliasing was handled at a higher
681 // level
682 private Option canonicalize(Option option) {
683 switch (option) {
684 case XBOOTCLASSPATH:
685 return Option.BOOTCLASSPATH;
686 case DJAVA_ENDORSED_DIRS:
687 return Option.ENDORSEDDIRS;
688 case DJAVA_EXT_DIRS:
689 return Option.EXTDIRS;
690 default:
691 return option;
692 }
693 }
694
695 @Override
696 Collection<Path> getPaths() {
697 lazy();
698 return searchPath;
699 }
700
701 @Override
702 void setPaths(Iterable<? extends Path> files) {
703 if (files == null) {
704 searchPath = null; // reset to "uninitialized"
705 } else {
706 isDefault = false;
707 SearchPath p = new SearchPath().addFiles(files, false);
708 searchPath = Collections.unmodifiableCollection(p);
709 optionValues.clear();
710 }
711 }
712
713 SearchPath computePath() throws IOException {
714 SearchPath path = new SearchPath();
715
716 String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
717 String endorseddirsOpt = optionValues.get(ENDORSEDDIRS);
718 String extdirsOpt = optionValues.get(EXTDIRS);
719 String xbootclasspathPrependOpt = optionValues.get(XBOOTCLASSPATH_PREPEND);
720 String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND);
721 path.addFiles(xbootclasspathPrependOpt);
722
723 if (endorseddirsOpt != null) {
724 path.addDirectories(endorseddirsOpt);
725 } else {
726 path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
727 }
728
729 if (bootclasspathOpt != null) {
730 path.addFiles(bootclasspathOpt);
731 } else {
732 // Standard system classes for this compiler's release.
733 Collection<Path> systemClasses = systemClasses();
734 if (systemClasses != null) {
735 path.addFiles(systemClasses, false);
736 } else {
1144 return null;
1145 }
1146
1147 private String readModuleName(Path path) throws IOException, ModuleNameReader.BadClassFile {
1148 if (moduleNameReader == null)
1149 moduleNameReader = new ModuleNameReader();
1150 return moduleNameReader.readModuleName(path);
1151 }
1152 }
1153
1154 }
1155
1156 private class ModuleSourcePathLocationHandler extends BasicLocationHandler {
1157
1158 private Map<String, Location> moduleLocations;
1159 private Map<Path, Location> pathLocations;
1160
1161
1162 ModuleSourcePathLocationHandler() {
1163 super(StandardLocation.MODULE_SOURCE_PATH,
1164 Option.MODULESOURCEPATH);
1165 }
1166
1167 @Override
1168 boolean handleOption(Option option, String value) {
1169 init(value);
1170 return true;
1171 }
1172
1173 void init(String value) {
1174 Collection<String> segments = new ArrayList<>();
1175 for (String s: value.split(File.pathSeparator)) {
1176 expandBraces(s, segments);
1177 }
1178
1179 Map<String, Collection<Path>> map = new LinkedHashMap<>();
1180 final String MARKER = "*";
1181 for (String seg: segments) {
1182 int markStart = seg.indexOf(MARKER);
1183 if (markStart == -1) {
1184 add(map, getPath(seg), null);
1476 String moduleName = entry.getFileName().toString();
1477 String name = location.getName() + "[" + moduleName + "]";
1478 ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName,
1479 Collections.singleton(entry), false, true);
1480 systemModules.put(moduleName, h);
1481 }
1482 }
1483 }
1484 }
1485
1486 Map<Location, LocationHandler> handlersForLocation;
1487 Map<Option, LocationHandler> handlersForOption;
1488
1489 void initHandlers() {
1490 handlersForLocation = new HashMap<>();
1491 handlersForOption = new EnumMap<>(Option.class);
1492
1493 BasicLocationHandler[] handlers = {
1494 new BootClassPathLocationHandler(),
1495 new ClassPathLocationHandler(),
1496 new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH),
1497 new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH),
1498 new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSORMODULEPATH),
1499 new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
1500 new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
1501 new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
1502 new ModuleSourcePathLocationHandler(),
1503 // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES?
1504 new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADEMODULEPATH),
1505 new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULEPATH, Option.MP),
1506 new SystemModulesLocationHandler(),
1507 };
1508
1509 for (BasicLocationHandler h : handlers) {
1510 handlersForLocation.put(h.location, h);
1511 for (Option o : h.options) {
1512 handlersForOption.put(o, h);
1513 }
1514 }
1515 }
1516
1517 private Map<String, SearchPath> patchMap;
1518
1519 boolean handleOption(Option option, String value) {
1520 switch (option) {
1521 case XPATCH:
1522 Map<String, SearchPath> map = new LinkedHashMap<>();
1523 int eq = value.indexOf('=');
1524 if (eq > 0) {
1525 String mName = value.substring(0, eq);
1526 SearchPath mPatchPath = new SearchPath()
1527 .addFiles(value.substring(eq + 1));
1528 boolean ok = true;
1529 for (Path p: mPatchPath) {
1530 Path mi = p.resolve("module-info.class");
1531 if (Files.exists(mi)) {
1532 log.error(Errors.LocnModuleInfoNotAllowedOnPatchPath(mi));
1533 ok = false;
1534 }
1535 }
1536 if (ok && !mPatchPath.isEmpty()) {
1537 map.computeIfAbsent(mName, (_x) -> new SearchPath())
1538 .addAll(mPatchPath);
1539 }
1540 } else {
1541 log.error(Errors.LocnInvalidArgForXpatch(value));
1542 }
1543 patchMap = map;
1544 return true;
1545 default:
1546 LocationHandler h = handlersForOption.get(option);
1547 return (h == null ? false : h.handleOption(option, value));
1548 }
1549 }
1550
1551 boolean hasLocation(Location location) {
1552 LocationHandler h = getHandler(location);
1553 return (h == null ? false : h.isSet());
1554 }
1555
1556 Collection<Path> getLocation(Location location) {
1557 LocationHandler h = getHandler(location);
1558 return (h == null ? null : h.getPaths());
1559 }
1560
1561 Path getOutputLocation(Location location) {
1562 if (!location.isOutputLocation()) {
1563 throw new IllegalArgumentException();
|
67 import javax.lang.model.SourceVersion;
68 import javax.tools.JavaFileManager;
69 import javax.tools.JavaFileManager.Location;
70 import javax.tools.StandardJavaFileManager;
71 import javax.tools.StandardJavaFileManager.PathFactory;
72 import javax.tools.StandardLocation;
73
74 import com.sun.tools.javac.code.Lint;
75 import com.sun.tools.javac.main.Option;
76 import com.sun.tools.javac.resources.CompilerProperties.Errors;
77 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
78 import com.sun.tools.javac.util.DefinedBy;
79 import com.sun.tools.javac.util.DefinedBy.Api;
80 import com.sun.tools.javac.util.ListBuffer;
81 import com.sun.tools.javac.util.Log;
82 import com.sun.tools.javac.util.Pair;
83 import com.sun.tools.javac.util.StringUtils;
84
85 import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
86
87 import static com.sun.tools.javac.main.Option.BOOT_CLASS_PATH;
88 import static com.sun.tools.javac.main.Option.DJAVA_ENDORSED_DIRS;
89 import static com.sun.tools.javac.main.Option.DJAVA_EXT_DIRS;
90 import static com.sun.tools.javac.main.Option.ENDORSEDDIRS;
91 import static com.sun.tools.javac.main.Option.EXTDIRS;
92 import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH;
93 import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_APPEND;
94 import static com.sun.tools.javac.main.Option.XBOOTCLASSPATH_PREPEND;
95
96 /**
97 * This class converts command line arguments, environment variables and system properties (in
98 * File.pathSeparator-separated String form) into a boot class path, user class path, and source
99 * path (in {@code Collection<String>} form).
100 *
101 * <p>
102 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
103 * your own risk. This code and its internal interfaces are subject to change or deletion without
104 * notice.</b>
105 */
106 public class Locations {
107
563 }
564 searchPath = Collections.unmodifiableCollection(p);
565 }
566
567 protected SearchPath computePath(String value) {
568 return createPath().addFiles(value);
569 }
570
571 protected SearchPath createPath() {
572 return new SearchPath();
573 }
574 }
575
576 /**
577 * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
578 * If no value is given, a default is provided, based on system properties and other values.
579 */
580 private class ClassPathLocationHandler extends SimpleLocationHandler {
581
582 ClassPathLocationHandler() {
583 super(StandardLocation.CLASS_PATH, Option.CLASS_PATH);
584 }
585
586 @Override
587 Collection<Path> getPaths() {
588 lazy();
589 return searchPath;
590 }
591
592 @Override
593 protected SearchPath computePath(String value) {
594 String cp = value;
595
596 // CLASSPATH environment variable when run from `javac'.
597 if (cp == null) {
598 cp = System.getProperty("env.class.path");
599 }
600
601 // If invoked via a java VM (not the javac launcher), use the
602 // platform class path
603 if (cp == null && System.getProperty("application.home") == null) {
631 * Various options are supported for different components of the
632 * platform class path.
633 * Setting a value with setLocation overrides all existing option values.
634 * Setting any option overrides any value set with setLocation, and
635 * reverts to using default values for options that have not been set.
636 * Setting -bootclasspath or -Xbootclasspath overrides any existing
637 * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
638 */
639 private class BootClassPathLocationHandler extends BasicLocationHandler {
640
641 private Collection<Path> searchPath;
642 final Map<Option, String> optionValues = new EnumMap<>(Option.class);
643
644 /**
645 * Is the bootclasspath the default?
646 */
647 private boolean isDefault;
648
649 BootClassPathLocationHandler() {
650 super(StandardLocation.PLATFORM_CLASS_PATH,
651 Option.BOOT_CLASS_PATH, Option.XBOOTCLASSPATH,
652 Option.XBOOTCLASSPATH_PREPEND,
653 Option.XBOOTCLASSPATH_APPEND,
654 Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
655 Option.EXTDIRS, Option.DJAVA_EXT_DIRS);
656 }
657
658 boolean isDefault() {
659 lazy();
660 return isDefault;
661 }
662
663 @Override
664 boolean handleOption(Option option, String value) {
665 if (!options.contains(option)) {
666 return false;
667 }
668
669 option = canonicalize(option);
670 optionValues.put(option, value);
671 if (option == BOOT_CLASS_PATH) {
672 optionValues.remove(XBOOTCLASSPATH_PREPEND);
673 optionValues.remove(XBOOTCLASSPATH_APPEND);
674 }
675 searchPath = null; // reset to "uninitialized"
676 return true;
677 }
678 // where
679 // TODO: would be better if option aliasing was handled at a higher
680 // level
681 private Option canonicalize(Option option) {
682 switch (option) {
683 case XBOOTCLASSPATH:
684 return Option.BOOT_CLASS_PATH;
685 case DJAVA_ENDORSED_DIRS:
686 return Option.ENDORSEDDIRS;
687 case DJAVA_EXT_DIRS:
688 return Option.EXTDIRS;
689 default:
690 return option;
691 }
692 }
693
694 @Override
695 Collection<Path> getPaths() {
696 lazy();
697 return searchPath;
698 }
699
700 @Override
701 void setPaths(Iterable<? extends Path> files) {
702 if (files == null) {
703 searchPath = null; // reset to "uninitialized"
704 } else {
705 isDefault = false;
706 SearchPath p = new SearchPath().addFiles(files, false);
707 searchPath = Collections.unmodifiableCollection(p);
708 optionValues.clear();
709 }
710 }
711
712 SearchPath computePath() throws IOException {
713 SearchPath path = new SearchPath();
714
715 String bootclasspathOpt = optionValues.get(BOOT_CLASS_PATH);
716 String endorseddirsOpt = optionValues.get(ENDORSEDDIRS);
717 String extdirsOpt = optionValues.get(EXTDIRS);
718 String xbootclasspathPrependOpt = optionValues.get(XBOOTCLASSPATH_PREPEND);
719 String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND);
720 path.addFiles(xbootclasspathPrependOpt);
721
722 if (endorseddirsOpt != null) {
723 path.addDirectories(endorseddirsOpt);
724 } else {
725 path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
726 }
727
728 if (bootclasspathOpt != null) {
729 path.addFiles(bootclasspathOpt);
730 } else {
731 // Standard system classes for this compiler's release.
732 Collection<Path> systemClasses = systemClasses();
733 if (systemClasses != null) {
734 path.addFiles(systemClasses, false);
735 } else {
1143 return null;
1144 }
1145
1146 private String readModuleName(Path path) throws IOException, ModuleNameReader.BadClassFile {
1147 if (moduleNameReader == null)
1148 moduleNameReader = new ModuleNameReader();
1149 return moduleNameReader.readModuleName(path);
1150 }
1151 }
1152
1153 }
1154
1155 private class ModuleSourcePathLocationHandler extends BasicLocationHandler {
1156
1157 private Map<String, Location> moduleLocations;
1158 private Map<Path, Location> pathLocations;
1159
1160
1161 ModuleSourcePathLocationHandler() {
1162 super(StandardLocation.MODULE_SOURCE_PATH,
1163 Option.MODULE_SOURCE_PATH);
1164 }
1165
1166 @Override
1167 boolean handleOption(Option option, String value) {
1168 init(value);
1169 return true;
1170 }
1171
1172 void init(String value) {
1173 Collection<String> segments = new ArrayList<>();
1174 for (String s: value.split(File.pathSeparator)) {
1175 expandBraces(s, segments);
1176 }
1177
1178 Map<String, Collection<Path>> map = new LinkedHashMap<>();
1179 final String MARKER = "*";
1180 for (String seg: segments) {
1181 int markStart = seg.indexOf(MARKER);
1182 if (markStart == -1) {
1183 add(map, getPath(seg), null);
1475 String moduleName = entry.getFileName().toString();
1476 String name = location.getName() + "[" + moduleName + "]";
1477 ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName,
1478 Collections.singleton(entry), false, true);
1479 systemModules.put(moduleName, h);
1480 }
1481 }
1482 }
1483 }
1484
1485 Map<Location, LocationHandler> handlersForLocation;
1486 Map<Option, LocationHandler> handlersForOption;
1487
1488 void initHandlers() {
1489 handlersForLocation = new HashMap<>();
1490 handlersForOption = new EnumMap<>(Option.class);
1491
1492 BasicLocationHandler[] handlers = {
1493 new BootClassPathLocationHandler(),
1494 new ClassPathLocationHandler(),
1495 new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCE_PATH),
1496 new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSOR_PATH),
1497 new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSOR_MODULE_PATH),
1498 new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
1499 new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
1500 new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
1501 new ModuleSourcePathLocationHandler(),
1502 // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES?
1503 new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADE_MODULE_PATH),
1504 new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULE_PATH),
1505 new SystemModulesLocationHandler(),
1506 };
1507
1508 for (BasicLocationHandler h : handlers) {
1509 handlersForLocation.put(h.location, h);
1510 for (Option o : h.options) {
1511 handlersForOption.put(o, h);
1512 }
1513 }
1514 }
1515
1516 private Map<String, SearchPath> patchMap;
1517
1518 boolean handleOption(Option option, String value) {
1519 switch (option) {
1520 case PATCH_MODULE:
1521 if (value == null) {
1522 patchMap = null;
1523 } else {
1524 // Allow an extended syntax for --patch-module consisting of a series
1525 // of values separated by NULL characters. This is to facilitate
1526 // supporting deferred file manager options on the command line.
1527 // See Option.PATCH_MODULE for the code that composes these multiple
1528 // values.
1529 for (String v : value.split("\0")) {
1530 int eq = v.indexOf('=');
1531 if (eq > 0) {
1532 String mName = v.substring(0, eq);
1533 SearchPath mPatchPath = new SearchPath()
1534 .addFiles(v.substring(eq + 1));
1535 boolean ok = true;
1536 for (Path p : mPatchPath) {
1537 Path mi = p.resolve("module-info.class");
1538 if (Files.exists(mi)) {
1539 log.error(Errors.LocnModuleInfoNotAllowedOnPatchPath(mi));
1540 ok = false;
1541 }
1542 }
1543 if (ok) {
1544 if (patchMap == null) {
1545 patchMap = new LinkedHashMap<>();
1546 }
1547 patchMap.put(mName, mPatchPath);
1548 }
1549 } else {
1550 // Should not be able to get here;
1551 // this should be caught and handled in Option.PATCH_MODULE
1552 log.error(Errors.LocnInvalidArgForXpatch(value));
1553 }
1554 }
1555 }
1556 return true;
1557 default:
1558 LocationHandler h = handlersForOption.get(option);
1559 return (h == null ? false : h.handleOption(option, value));
1560 }
1561 }
1562
1563 boolean hasLocation(Location location) {
1564 LocationHandler h = getHandler(location);
1565 return (h == null ? false : h.isSet());
1566 }
1567
1568 Collection<Path> getLocation(Location location) {
1569 LocationHandler h = getHandler(location);
1570 return (h == null ? null : h.getPaths());
1571 }
1572
1573 Path getOutputLocation(Location location) {
1574 if (!location.isOutputLocation()) {
1575 throw new IllegalArgumentException();
|