12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.module;
27
28 import java.io.InputStream;
29 import java.io.IOException;
30 import java.io.PrintStream;
31 import java.io.UncheckedIOException;
32 import java.net.URI;
33 import java.nio.ByteBuffer;
34 import java.nio.file.Path;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.EnumSet;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.LinkedHashSet;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Objects;
45 import java.util.Optional;
46 import java.util.Set;
47 import java.util.function.Supplier;
48 import java.util.stream.Collectors;
49 import java.util.stream.Stream;
50
51 import static jdk.internal.module.Checks.*;
52 import static java.util.Objects.*;
53
54 import jdk.internal.module.Checks;
55 import jdk.internal.module.ModuleHashes;
56
57
58 /**
59 * A module descriptor.
60 *
61 * <p> A {@code ModuleDescriptor} is typically created from the binary form
62 * of a module declaration. Alternatively, the {@link ModuleDescriptor.Builder}
63 * class can be used to create a {@code ModuleDescriptor} from its components.
64 * The {@link #module module}, {@link #openModule openModule}, and {@link
65 * #automaticModule automaticModule} methods create builders for building
66 * different kinds of modules. </p>
67 *
68 * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
69 * multiple concurrent threads.</p>
70 *
71 * @since 9
72 * @see java.lang.reflect.Module
73 */
74
75 public class ModuleDescriptor
106 * but is optional in the dynamic phase, during execution.
107 */
108 STATIC,
109
110 /**
111 * The dependence was not explicitly or implicitly declared in the
112 * source of the module declaration.
113 */
114 SYNTHETIC,
115
116 /**
117 * The dependence was implicitly declared in the source of the module
118 * declaration.
119 */
120 MANDATED;
121
122 }
123
124 private final Set<Modifier> mods;
125 private final String name;
126
127 private Requires(Set<Modifier> ms, String mn) {
128 if (ms.isEmpty()) {
129 ms = Collections.emptySet();
130 } else {
131 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
132 }
133 this.mods = ms;
134 this.name = mn;
135 }
136
137 private Requires(Set<Modifier> ms, String mn, boolean unused) {
138 this.mods = ms;
139 this.name = mn;
140 }
141
142 /**
143 * Returns the set of modifiers.
144 *
145 * @return A possibly-empty unmodifiable set of modifiers
146 */
147 public Set<Modifier> modifiers() {
148 return mods;
149 }
150
151 /**
152 * Return the module name.
153 *
154 * @return The module name
155 */
156 public String name() {
157 return name;
158 }
159
160 /**
161 * Compares this module dependence to another.
162 *
163 * <p> Two {@code Requires} objects are compared by comparing their
164 * module name lexicographically. Where the module names are equal then
165 * the sets of modifiers are compared based on a value computed from the
166 * ordinal of each modifier. </p>
167 *
168 * @return A negative integer, zero, or a positive integer if this module
169 * dependence is less than, equal to, or greater than the given
170 * module dependence
171 */
172 @Override
173 public int compareTo(Requires that) {
174 int c = this.name().compareTo(that.name());
175 if (c != 0)
176 return c;
177 // same name, compare by modifiers
178 return Long.compare(this.modsValue(), that.modsValue());
179 }
180
181 /**
182 * Return a value for the modifiers to allow sets of modifiers to be
183 * compared.
184 */
185 private long modsValue() {
186 long value = 0;
187 for (Modifier m : mods) {
188 value += 1 << m.ordinal();
189 }
190 return value;
191 }
192
193 /**
194 * Tests this module dependence for equality with the given object.
195 *
196 * <p> If the given object is not a {@code Requires} then this method
197 * returns {@code false}. Two module dependence objects are equal if
198 * the module names are equal and set of modifiers are equal. </p>
199 *
200 * <p> This method satisfies the general contract of the {@link
201 * java.lang.Object#equals(Object) Object.equals} method. </p>
202 *
203 * @param ob
204 * the object to which this object is to be compared
205 *
206 * @return {@code true} if, and only if, the given object is a module
207 * dependence that is equal to this module dependence
208 */
209 @Override
210 public boolean equals(Object ob) {
211 if (!(ob instanceof Requires))
212 return false;
213 Requires that = (Requires)ob;
214 return (name.equals(that.name) && mods.equals(that.mods));
215 }
216
217 /**
218 * Computes a hash code for this module dependence.
219 *
220 * <p> The hash code is based upon the module name and modifiers. It
221 * satisfies the general contract of the {@link Object#hashCode
222 * Object.hashCode} method. </p>
223 *
224 * @return The hash-code value for this module dependence
225 */
226 @Override
227 public int hashCode() {
228 return name.hashCode() * 43 + mods.hashCode();
229 }
230
231 /**
232 * Returns a string describing module dependence.
233 *
234 * @return A string describing module dependence
235 */
236 @Override
237 public String toString() {
238 return ModuleDescriptor.toString(mods, name);
239 }
240 }
241
242
243
244 /**
245 * <p> A module export, may be qualified or unqualified. </p>
246 *
247 * @see ModuleDescriptor#exports()
248 * @since 9
249 */
250
251 public final static class Exports {
252
253 /**
254 * A modifier on a module export.
255 *
256 * @since 9
257 */
258 public static enum Modifier {
950 * @return The hash-code value for this module version
951 */
952 @Override
953 public int hashCode() {
954 return version.hashCode();
955 }
956
957 /**
958 * Returns the string from which this version was parsed.
959 *
960 * @return The string from which this version was parsed.
961 */
962 @Override
963 public String toString() {
964 return version;
965 }
966
967 }
968
969
970
971 // From module declarations
972 private final String name;
973 private final boolean open;
974
975 // Indicates if synthesised for a JAR file found on the module path
976 private final boolean automatic;
977
978 // Not generated from a module-info.java
979 private final boolean synthetic;
980
981 private final Set<Requires> requires;
982 private final Set<Exports> exports;
983 private final Set<Opens> opens;
984 private final Set<String> uses;
985 private final Set<Provides> provides;
986
987 // "Extended" information, added post-compilation by tools
988 private final Version version;
989 private final String mainClass;
990 private final String osName;
991 private final String osArch;
992 private final String osVersion;
993 private final Set<String> packages;
994 private final ModuleHashes hashes;
995
996
997 private ModuleDescriptor(String name,
998 boolean open,
999 boolean automatic,
1000 boolean synthetic,
1001 Set<Requires> requires,
1002 Set<Exports> exports,
1003 Set<Opens> opens,
1004 Set<String> uses,
1005 Set<Provides> provides,
1006 Version version,
1007 String mainClass,
1008 String osName,
1009 String osArch,
1010 String osVersion,
1011 Set<String> packages,
1012 ModuleHashes hashes)
1013 {
1014
1015 this.name = name;
1016 this.open = open;
1017 this.automatic = automatic;
1018 this.synthetic = synthetic;
1019
1020 assert (requires.stream().map(Requires::name).distinct().count()
1021 == requires.size());
1022 this.requires = emptyOrUnmodifiableSet(requires);
1023
1024 this.exports = emptyOrUnmodifiableSet(exports);
1025 this.opens = emptyOrUnmodifiableSet(opens);
1026 this.uses = emptyOrUnmodifiableSet(uses);
1027 this.provides = emptyOrUnmodifiableSet(provides);
1028 this.version = version;
1029 this.mainClass = mainClass;
1030 this.osName = osName;
1031 this.osArch = osArch;
1032 this.osVersion = osVersion;
1033 this.hashes = hashes;
1034 this.packages = emptyOrUnmodifiableSet(packages);
1035 }
1036
1037 /**
1038 * Clones the given module descriptor with an augmented set of packages
1039 */
1040 ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) {
1041 this.name = md.name;
1042 this.open = md.open;
1043 this.automatic = md.automatic;
1044 this.synthetic = md.synthetic;
1045
1046 this.requires = md.requires;
1047 this.exports = md.exports;
1048 this.opens = md.opens;
1049 this.uses = md.uses;
1050 this.provides = md.provides;
1051
1052 this.version = md.version;
1053 this.mainClass = md.mainClass;
1054 this.osName = md.osName;
1055 this.osArch = md.osArch;
1056 this.osVersion = md.osVersion;
1057 this.hashes = null; // need to ignore
1058
1059 Set<String> packages = new HashSet<>(md.packages);
1060 packages.addAll(pkgs);
1061 this.packages = emptyOrUnmodifiableSet(packages);
1062 }
1063
1064 /**
1065 * Creates a module descriptor from its components.
1066 * The arguments are pre-validated and sets are unmodifiable sets.
1067 */
1068 ModuleDescriptor(String name,
1069 boolean open,
1070 boolean automatic,
1071 boolean synthetic,
1072 Set<Requires> requires,
1073 Set<Exports> exports,
1074 Set<Opens> opens,
1075 Set<String> uses,
1076 Set<Provides> provides,
1077 Version version,
1078 String mainClass,
1079 String osName,
1080 String osArch,
1081 String osVersion,
1082 Set<String> packages,
1083 ModuleHashes hashes,
1084 int hashCode,
1085 boolean unused) {
1086 this.name = name;
1087 this.open = open;
1088 this.automatic = automatic;
1089 this.synthetic = synthetic;
1090 this.requires = requires;
1091 this.exports = exports;
1092 this.opens = opens;
1093 this.uses = uses;
1094 this.provides = provides;
1095 this.packages = packages;
1096 this.version = version;
1097 this.mainClass = mainClass;
1098 this.osName = osName;
1099 this.osArch = osArch;
1100 this.osVersion = osVersion;
1101 this.hashes = hashes;
1102 this.hash = hashCode;
1103 }
1104
1105 /**
1106 * <p> The module name. </p>
1107 *
1108 * @return The module name
1109 */
1110 public String name() {
1111 return name;
1112 }
1113
1114 /**
1115 * <p> Returns {@code true} if this is an open module. </p>
1116 *
1117 * <p> An open module does not declare any open packages (the {@link #opens()
1118 * opens} method returns an empty set) but the resulting module is treated
1119 * as if all packages are open. </p>
1120 *
1121 * @return {@code true} if this is an open module
1267 /**
1268 * Returns the operating system version if this module is operating
1269 * system version specific.
1270 *
1271 * @return The operating system version or an empty {@code Optional}
1272 * if this module is not operating system version specific
1273 */
1274 public Optional<String> osVersion() {
1275 return Optional.ofNullable(osVersion);
1276 }
1277
1278 /**
1279 * Returns the names of all packages in this module.
1280 *
1281 * @return A possibly-empty unmodifiable set of all packages in the module
1282 */
1283 public Set<String> packages() {
1284 return packages;
1285 }
1286
1287 /**
1288 * Returns the object with the hashes of other modules
1289 */
1290 Optional<ModuleHashes> hashes() {
1291 return Optional.ofNullable(hashes);
1292 }
1293
1294
1295 /**
1296 * A builder used for building {@link ModuleDescriptor} objects.
1297 *
1298 * <p> {@code ModuleDescriptor} defines the {@link #module module}, {@link
1299 * #openModule openModule}, and {@link #automaticModule automaticModule}
1300 * methods to create builders for building different kinds of modules. </p>
1301 *
1302 * <p> Example usage: </p>
1303 * <pre>{@code ModuleDescriptor descriptor = ModuleDescriptor.module("m1")
1304 * .exports("p")
1305 * .requires("m2")
1306 * .build();
1307 * }</pre>
1308 *
1309 * @apiNote A {@code Builder} checks the components and invariants as
1310 * components are added to the builder. The rational for this is to detect
1311 * errors as early as possible and not defer all validation to the
1312 * {@link #build build} method. A {@code Builder} cannot be used to create
1313 * a {@link ModuleDescriptor#isSynthetic() synthetic} module.
1314 *
1315 * @since 9
1316 */
1317 public static final class Builder {
1318 final String name;
1319 final boolean strict; // true if module names are checked
1320 boolean open;
1321 boolean automatic;
1322 boolean synthetic;
1323 final Map<String, Requires> requires = new HashMap<>();
1324
1325 final Map<String, Exports> exports = new HashMap<>();
1326 final Map<String, Opens> opens = new HashMap<>();
1327 final Set<String> concealedPackages = new HashSet<>();
1328
1329 final Set<String> uses = new HashSet<>();
1330 final Map<String, Provides> provides = new HashMap<>();
1331 Version version;
1332 String osName;
1333 String osArch;
1334 String osVersion;
1335 String mainClass;
1336 ModuleHashes hashes;
1337
1338 /**
1339 * Initializes a new builder with the given module name.
1340 *
1341 * @param strict
1342 * Indicates whether module names are checked or not
1343 */
1344 Builder(String name, boolean strict) {
1345 this.strict = strict;
1346 this.name = (strict) ? requireModuleName(name) : name;
1347 }
1348
1349 /* package */ Builder open(boolean open) {
1350 this.open = open;
1351 return this;
1352 }
1353
1354 /* package */ Builder automatic(boolean automatic) {
1355 this.automatic = automatic;
1356 return this;
1357 }
1358
1359 /* package */ boolean isOpen() { return open; }
1360
1361 /* package */ boolean isAutomatic() {
1362 return automatic;
1363 }
1364
1365 /**
1366 * Adds a dependence on a module.
1367 *
1368 * @param req
1369 * The dependence
1370 *
1371 * @return This builder
1372 *
1373 * @throws IllegalArgumentException
1374 * If the dependence is on the module that this builder was
1375 * initialized to build
1376 * @throws IllegalStateException
1377 * If the dependence on the module has already been declared
1378 */
1379 public Builder requires(Requires req) {
1380 String mn = req.name();
1381 if (name.equals(mn))
1382 throw new IllegalArgumentException("Dependence on self");
1383 if (requires.containsKey(mn))
1384 throw new IllegalStateException("Dependence upon " + mn
1385 + " already declared");
1386 requires.put(mn, req);
1387 return this;
1388 }
1389
1390 /**
1391 * Adds a dependence on a module with the given (and possibly empty)
1392 * set of modifiers.
1393 *
1394 * @param ms
1395 * The set of modifiers
1396 * @param mn
1397 * The module name
1398 *
1399 * @return This builder
1400 *
1401 * @throws IllegalArgumentException
1402 * If the module name is {@code null}, is not a legal Java
1403 * identifier, or is equal to the module name that this builder
1404 * was initialized to build
1405 * @throws IllegalStateException
1406 * If the dependence on the module has already been declared
1407 */
1408 public Builder requires(Set<Requires.Modifier> ms, String mn) {
1409 if (strict)
1410 mn = requireModuleName(mn);
1411 return requires(new Requires(ms, mn));
1412 }
1413
1414 /**
1415 * Adds a dependence on a module with an empty set of modifiers.
1416 *
1417 * @param mn
1418 * The module name
1419 *
1420 * @return This builder
1421 *
1422 * @throws IllegalArgumentException
1423 * If the module name is {@code null}, is not a legal Java
1424 * identifier, or is equal to the module name that this builder
1425 * was initialized to build
1426 * @throws IllegalStateException
1427 * If the dependence on the module has already been declared
1428 */
1429 public Builder requires(String mn) {
1430 return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
1431 }
1688 /**
1689 * Adds an <em>opens</em> directive to open a package.
1690 *
1691 * @param pn
1692 * The package name
1693 *
1694 * @return This builder
1695 *
1696 * @throws IllegalArgumentException
1697 * If the package name is {@code null} or is not a legal Java
1698 * identifier
1699 * @throws IllegalStateException
1700 * If the package is already declared as a package with the
1701 * {@link #contains contains} method, the package is already
1702 * declared as open, or this is a builder for an open module
1703 */
1704 public Builder opens(String pn) {
1705 return opens(Collections.emptySet(), pn);
1706 }
1707
1708
1709 // Used by ModuleInfo, after a packageFinder is invoked
1710 /* package */ Set<String> exportedAndOpenPackages() {
1711 if (opens.isEmpty())
1712 return exports.keySet();
1713 Set<String> result = new HashSet<>();
1714 result.addAll(exports.keySet());
1715 result.addAll(opens.keySet());
1716 return result;
1717 }
1718
1719 /**
1720 * Adds a service dependence.
1721 *
1722 * @param service
1723 * The service type
1724 *
1725 * @return This builder
1726 *
1727 * @throws IllegalArgumentException
1728 * If the service type is {@code null} or is not a legal Java
1729 * identifier
1730 * @throws IllegalStateException
1731 * If a dependency on the service type has already been declared
1732 */
1733 public Builder uses(String service) {
1734 if (uses.contains(requireServiceTypeName(service)))
1735 throw new IllegalStateException("Dependence upon service "
1736 + service + " already declared");
1737 uses.add(service);
1738 return this;
1772 * @throws IllegalArgumentException
1773 * If the service type or any of the provider class names is
1774 * {@code null} or is not a legal Java identifier, or the list
1775 * of provider class names is empty
1776 * @throws IllegalStateException
1777 * If the providers for the service type have already been
1778 * declared
1779 */
1780 public Builder provides(String service, List<String> providers) {
1781 if (provides.containsKey(service))
1782 throw new IllegalStateException("Providers of service "
1783 + service + " already declared by " + name);
1784
1785 Provides p = new Provides(requireServiceTypeName(service), providers);
1786
1787 // check providers after the set has been copied.
1788 List<String> providerNames = p.providers();
1789 if (providerNames.isEmpty())
1790 throw new IllegalArgumentException("Empty providers set");
1791 providerNames.forEach(Checks::requireServiceProviderName);
1792
1793 provides.put(service, p);
1794 return this;
1795 }
1796
1797 /**
1798 * Provides an implementation of a service.
1799 *
1800 * @param service
1801 * The service type
1802 * @param provider
1803 * The provider or provider factory class name
1804 *
1805 * @return This builder
1806 *
1807 * @throws IllegalArgumentException
1808 * If the service type or the provider class name is {@code
1809 * null} or is not a legal Java identifier
1810 * @throws IllegalStateException
1811 * If the providers for the service type have already been
1812 * declared
1897 * If {@code v} is null or cannot be parsed as a version string
1898 *
1899 * @see Version#parse(String)
1900 */
1901 public Builder version(String v) {
1902 return version(Version.parse(v));
1903 }
1904
1905 /**
1906 * Sets the module main class.
1907 *
1908 * @param mc
1909 * The module main class
1910 *
1911 * @return This builder
1912 *
1913 * @throws IllegalArgumentException
1914 * If {@code mainClass} is null or is not a legal Java identifier
1915 */
1916 public Builder mainClass(String mc) {
1917 mainClass = requireJavaIdentifier("main class name", mc);
1918 return this;
1919 }
1920
1921 /**
1922 * Sets the operating system name.
1923 *
1924 * @param name
1925 * The operating system name
1926 *
1927 * @return This builder
1928 *
1929 * @throws IllegalArgumentException
1930 * If {@code name} is null or the empty String
1931 */
1932 public Builder osName(String name) {
1933 if (name == null || name.isEmpty())
1934 throw new IllegalArgumentException("OS name is null or empty");
1935 osName = name;
1936 return this;
1937 }
1955 }
1956
1957 /**
1958 * Sets the operating system version.
1959 *
1960 * @param version
1961 * The operating system version
1962 *
1963 * @return This builder
1964 *
1965 * @throws IllegalArgumentException
1966 * If {@code name} is null or the empty String
1967 */
1968 public Builder osVersion(String version) {
1969 if (version == null || version.isEmpty())
1970 throw new IllegalArgumentException("OS version is null or empty");
1971 osVersion = version;
1972 return this;
1973 }
1974
1975 /* package */ Builder hashes(ModuleHashes hashes) {
1976 this.hashes = hashes;
1977 return this;
1978 }
1979
1980 /* package */ Builder synthetic(boolean v) {
1981 this.synthetic = v;
1982 return this;
1983 }
1984
1985 /**
1986 * Builds and returns a {@code ModuleDescriptor} from its components.
1987 *
1988 * @return The module descriptor
1989 */
1990 public ModuleDescriptor build() {
1991 Set<Requires> requires = new HashSet<>(this.requires.values());
1992
1993 Set<String> packages = new HashSet<>(exportedAndOpenPackages());
1994 packages.addAll(concealedPackages);
1995
1996 Set<Exports> exports = new HashSet<>(this.exports.values());
1997 Set<Opens> opens = new HashSet<>(this.opens.values());
1998
1999 Set<Provides> provides = new HashSet<>(this.provides.values());
2000
2001 return new ModuleDescriptor(name,
2002 open,
2003 automatic,
2004 synthetic,
2005 requires,
2006 exports,
2007 opens,
2008 uses,
2009 provides,
2010 version,
2011 mainClass,
2012 osName,
2013 osArch,
2014 osVersion,
2015 packages,
2016 hashes);
2017 }
2018
2019 }
2020
2021 /**
2022 * Compares this module descriptor to another.
2023 *
2024 * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
2025 * module name lexicographically. Where the module names are equal then
2026 * the versions, if present, are compared. </p>
2027 *
2028 * @apiNote For now, the natural ordering is not consistent with equals.
2029 * If two module descriptors have equal module names, equal versions if
2030 * present, but their corresponding components are not equal, then they
2031 * will be considered equal by this method.
2032 *
2033 * @param that
2034 * The object to which this module descriptor is to be compared
2035 *
2036 * @return A negative integer, zero, or a positive integer if this module
2071 public boolean equals(Object ob) {
2072 if (ob == this)
2073 return true;
2074 if (!(ob instanceof ModuleDescriptor))
2075 return false;
2076 ModuleDescriptor that = (ModuleDescriptor)ob;
2077 return (name.equals(that.name)
2078 && open == that.open
2079 && automatic == that.automatic
2080 && synthetic == that.synthetic
2081 && requires.equals(that.requires)
2082 && exports.equals(that.exports)
2083 && opens.equals(that.opens)
2084 && uses.equals(that.uses)
2085 && provides.equals(that.provides)
2086 && Objects.equals(version, that.version)
2087 && Objects.equals(mainClass, that.mainClass)
2088 && Objects.equals(osName, that.osName)
2089 && Objects.equals(osArch, that.osArch)
2090 && Objects.equals(osVersion, that.osVersion)
2091 && Objects.equals(packages, that.packages)
2092 && Objects.equals(hashes, that.hashes));
2093 }
2094
2095 private transient int hash; // cached hash code
2096
2097 /**
2098 * Computes a hash code for this module descriptor.
2099 *
2100 * <p> The hash code is based upon the components of the module descriptor,
2101 * and satisfies the general contract of the {@link Object#hashCode
2102 * Object.hashCode} method. </p>
2103 *
2104 * @return The hash-code value for this module descriptor
2105 */
2106 @Override
2107 public int hashCode() {
2108 int hc = hash;
2109 if (hc == 0) {
2110 hc = name.hashCode();
2111 hc = hc * 43 + Boolean.hashCode(open);
2112 hc = hc * 43 + Boolean.hashCode(automatic);
2113 hc = hc * 43 + Boolean.hashCode(synthetic);
2114 hc = hc * 43 + requires.hashCode();
2115 hc = hc * 43 + exports.hashCode();
2116 hc = hc * 43 + opens.hashCode();
2117 hc = hc * 43 + uses.hashCode();
2118 hc = hc * 43 + provides.hashCode();
2119 hc = hc * 43 + Objects.hashCode(version);
2120 hc = hc * 43 + Objects.hashCode(mainClass);
2121 hc = hc * 43 + Objects.hashCode(osName);
2122 hc = hc * 43 + Objects.hashCode(osArch);
2123 hc = hc * 43 + Objects.hashCode(osVersion);
2124 hc = hc * 43 + Objects.hashCode(packages);
2125 hc = hc * 43 + Objects.hashCode(hashes);
2126 if (hc == 0)
2127 hc = -1;
2128 hash = hc;
2129 }
2130 return hc;
2131 }
2132
2133 /**
2134 * Returns a string describing this descriptor.
2135 *
2136 * @return A string describing this descriptor
2137 */
2138 @Override
2139 public String toString() {
2140 StringBuilder sb = new StringBuilder();
2141
2142 if (isOpen())
2143 sb.append("open ");
2144 sb.append("module { name: ").append(toNameAndVersion());
2145 if (!requires.isEmpty())
2146 sb.append(", ").append(requires);
2147 if (!uses.isEmpty())
2148 sb.append(", ").append(uses);
2149 if (!exports.isEmpty())
2150 sb.append(", exports: ").append(exports);
2151 if (!opens.isEmpty())
2152 sb.append(", opens: ").append(opens);
2153 if (!provides.isEmpty()) {
2154 sb.append(", provides: ").append(provides);
2155 }
2156 sb.append(" }");
2157 return sb.toString();
2158 }
2159
2160
2161 /**
2162 * Instantiates a builder to build a module descriptor.
2163 *
2164 * @param name
2165 * The module name
2166 *
2167 * @return A new builder
2168 *
2169 * @throws IllegalArgumentException
2170 * If the module name is {@code null} or is not a legal Java
2171 * identifier
2172 */
2173 public static Builder module(String name) {
2174 return new Builder(name, true);
2175 }
2176
2177 /**
2178 * Instantiates a builder to build a module descriptor for an open module.
2179 * An open module does not declare any open packages but the resulting
2180 * module is treated as if all packages are open.
2181 *
2182 * <p> As an example, the following creates a module descriptor for an open
2183 * name "{@code m}" containing two packages, one of which is exported. </p>
2184 * <pre>{@code
2185 * ModuleDescriptor descriptor = ModuleDescriptor.openModule("m")
2186 * .requires("java.base")
2187 * .exports("p")
2188 * .contains("q")
2189 * .build();
2190 * }</pre>
2191 *
2192 * @param name
2193 * The module name
2194 *
2195 * @return A new builder that builds an open module
2196 *
2197 * @throws IllegalArgumentException
2198 * If the module name is {@code null} or is not a legal Java
2199 * identifier
2200 */
2201 public static Builder openModule(String name) {
2202 return new Builder(name, true).open(true);
2203 }
2204
2205 /**
2206 * Instantiates a builder to build a module descriptor for an automatic
2207 * module. Automatic modules receive special treatment during resolution
2208 * (see {@link Configuration}) so that they read all other modules. When
2209 * Instantiated in the Java virtual machine as a {@link java.lang.reflect.Module}
2210 * then the Module reads every unnamed module in the Java virtual machine.
2211 *
2212 * @param name
2213 * The module name
2214 *
2215 * @return A new builder that builds an automatic module
2216 *
2217 * @throws IllegalArgumentException
2218 * If the module name is {@code null} or is not a legal Java
2219 * identifier
2220 *
2221 * @see ModuleFinder#of(Path[])
2222 */
2223 public static Builder automaticModule(String name) {
2224 return new Builder(name, true).automatic(true);
2225 }
2226
2227
2228 /**
2229 * Reads the binary form of a module declaration from an input stream
2230 * as a module descriptor.
2231 *
2232 * <p> If the descriptor encoded in the input stream does not indicate a
2233 * set of packages in the module then the {@code packageFinder} will be
2234 * invoked. If the {@code packageFinder} throws an {@link UncheckedIOException}
2235 * then {@link IOException} cause will be re-thrown. </p>
2236 *
2237 * <p> If there are bytes following the module descriptor then it is
2238 * implementation specific as to whether those bytes are read, ignored,
2239 * or reported as an {@code InvalidModuleDescriptorException}. If this
2240 * method fails with an {@code InvalidModuleDescriptorException} or {@code
2241 * IOException} then it may do so after some, but not all, bytes have
2242 * been read from the input stream. It is strongly recommended that the
2243 * stream be promptly closed and discarded if an exception occurs. </p>
2244 *
2246 * module descriptors from legacy module-artifact formats that do not
2247 * record the set of packages in the descriptor itself.
2248 *
2249 * @param in
2250 * The input stream
2251 * @param packageFinder
2252 * A supplier that can produce the set of packages
2253 *
2254 * @return The module descriptor
2255 *
2256 * @throws InvalidModuleDescriptorException
2257 * If an invalid module descriptor is detected
2258 * @throws IOException
2259 * If an I/O error occurs reading from the input stream or {@code
2260 * UncheckedIOException} is thrown by the package finder
2261 */
2262 public static ModuleDescriptor read(InputStream in,
2263 Supplier<Set<String>> packageFinder)
2264 throws IOException
2265 {
2266 return ModuleInfo.read(in, requireNonNull(packageFinder));
2267 }
2268
2269 /**
2270 * Reads the binary form of a module declaration from an input stream
2271 * as a module descriptor.
2272 *
2273 * @param in
2274 * The input stream
2275 *
2276 * @return The module descriptor
2277 *
2278 * @throws InvalidModuleDescriptorException
2279 * If an invalid module descriptor is detected
2280 * @throws IOException
2281 * If an I/O error occurs reading from the input stream
2282 */
2283 public static ModuleDescriptor read(InputStream in) throws IOException {
2284 return ModuleInfo.read(in, null);
2285 }
2286
2287 /**
2288 * Reads the binary form of a module declaration from a byte buffer
2289 * as a module descriptor.
2290 *
2291 * <p> If the descriptor encoded in the byte buffer does not indicate a
2292 * set of packages then the {@code packageFinder} will be invoked. </p>
2293 *
2294 * <p> The module descriptor is read from the buffer stating at index
2295 * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
2296 * position} when this method is invoked. Upon return the buffer's position
2297 * will be equal to {@code p + n} where {@code n} is the number of bytes
2298 * read from the buffer. </p>
2299 *
2300 * <p> If there are bytes following the module descriptor then it is
2301 * implementation specific as to whether those bytes are read, ignored,
2302 * or reported as an {@code InvalidModuleDescriptorException}. If this
2303 * method fails with an {@code InvalidModuleDescriptorException} then it
2304 * may do so after some, but not all, bytes have been read. </p>
2305 *
2306 * @apiNote The {@code packageFinder} parameter is for use when reading
2307 * module descriptors from legacy module-artifact formats that do not
2308 * record the set of packages in the descriptor itself.
2309 *
2310 * @param bb
2311 * The byte buffer
2312 * @param packageFinder
2313 * A supplier that can produce the set of packages
2314 *
2315 * @return The module descriptor
2316 *
2317 * @throws InvalidModuleDescriptorException
2318 * If an invalid module descriptor is detected
2319 */
2320 public static ModuleDescriptor read(ByteBuffer bb,
2321 Supplier<Set<String>> packageFinder)
2322 {
2323 return ModuleInfo.read(bb, requireNonNull(packageFinder));
2324 }
2325
2326 /**
2327 * Reads the binary form of a module declaration from a byte buffer
2328 * as a module descriptor.
2329 *
2330 * @param bb
2331 * The byte buffer
2332 *
2333 * @return The module descriptor
2334 *
2335 * @throws InvalidModuleDescriptorException
2336 * If an invalid module descriptor is detected
2337 */
2338 public static ModuleDescriptor read(ByteBuffer bb) {
2339 return ModuleInfo.read(bb, null);
2340 }
2341
2342 private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
2343 if (map.isEmpty()) {
2344 return Collections.emptyMap();
2345 } else if (map.size() == 1) {
2346 Map.Entry<K, V> entry = map.entrySet().iterator().next();
2347 return Collections.singletonMap(entry.getKey(), entry.getValue());
2348 } else {
2349 return Collections.unmodifiableMap(map);
2350 }
2351 }
2352
2353 private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) {
2354 if (set.isEmpty()) {
2355 return Collections.emptySet();
2356 } else if (set.size() == 1) {
2357 return Collections.singleton(set.iterator().next());
2358 } else {
2359 return Collections.unmodifiableSet(set);
2360 }
2361 }
2362
2363 /**
2364 * Returns a string containing the given set of modifiers and label.
2365 */
2366 private static <M> String toString(Set<M> mods, String what) {
2367 return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
2368 Stream.of(what)))
2369 .collect(Collectors.joining(" "));
2370 }
2371
2372 static {
2373 /**
2374 * Setup the shared secret to allow code in other packages access
2375 * private package methods in java.lang.module.
2376 */
2377 jdk.internal.misc.SharedSecrets
2378 .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
2379 @Override
2380 public Builder newModuleBuilder(String mn, boolean strict) {
2381 return new Builder(mn, strict);
2382 }
2383
2384 @Override
2385 public Builder newOpenModuleBuilder(String mn, boolean strict) {
2386 return new Builder(mn, strict).open(true);
2387 }
2388
2389 @Override
2390 public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
2391 return new Requires(ms, mn, true);
2392 }
2393
2394 @Override
2395 public Exports newExports(Set<Exports.Modifier> ms, String source) {
2396 return new Exports(ms, source, Collections.emptySet(), true);
2397 }
2398
2399 @Override
2400 public Exports newExports(Set<Exports.Modifier> ms,
2401 String source,
2402 Set<String> targets) {
2403 return new Exports(ms, source, targets, true);
2404 }
2405
2406 @Override
2407 public Opens newOpens(Set<Opens.Modifier> ms,
2408 String source,
2409 Set<String> targets) {
2410 return new Opens(ms, source, targets, true);
2411 }
2416 }
2417
2418 @Override
2419 public Provides newProvides(String service, List<String> providers) {
2420 return new Provides(service, providers, true);
2421 }
2422
2423 @Override
2424 public Version newVersion(String v) {
2425 return new Version(v);
2426 }
2427
2428 @Override
2429 public ModuleDescriptor newModuleDescriptor(ModuleDescriptor md,
2430 Set<String> pkgs) {
2431 return new ModuleDescriptor(md, pkgs);
2432 }
2433
2434 @Override
2435 public ModuleDescriptor newModuleDescriptor(String name,
2436 boolean open,
2437 boolean automatic,
2438 boolean synthetic,
2439 Set<Requires> requires,
2440 Set<Exports> exports,
2441 Set<Opens> opens,
2442 Set<String> uses,
2443 Set<Provides> provides,
2444 Version version,
2445 String mainClass,
2446 String osName,
2447 String osArch,
2448 String osVersion,
2449 Set<String> packages,
2450 ModuleHashes hashes,
2451 int hashCode) {
2452 return new ModuleDescriptor(name,
2453 open,
2454 automatic,
2455 synthetic,
2456 requires,
2457 exports,
2458 opens,
2459 uses,
2460 provides,
2461 version,
2462 mainClass,
2463 osName,
2464 osArch,
2465 osVersion,
2466 packages,
2467 hashes,
2468 hashCode,
2469 false);
2470 }
2471
2472 @Override
2473 public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
2474 return descriptor.hashes();
2475 }
2476
2477 @Override
2478 public Configuration resolveRequiresAndUses(ModuleFinder finder,
2479 Collection<String> roots,
2480 boolean check,
2481 PrintStream traceOutput)
2482 {
2483 return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
2484 }
2485
2486 @Override
2487 public ModuleReference newPatchedModule(ModuleDescriptor descriptor,
2488 URI location,
2489 Supplier<ModuleReader> s) {
2490 return new ModuleReference(descriptor, location, s, true, null);
2491 }
2492
2493 @Override
2494 public ModuleFinder newModulePath(Runtime.Version version,
2495 boolean isLinkPhase,
2496 Path... entries) {
2497 return new ModulePath(version, isLinkPhase, entries);
2498 }
2499 });
2500 }
2501
2502 }
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.module;
27
28 import java.io.InputStream;
29 import java.io.IOException;
30 import java.io.PrintStream;
31 import java.io.UncheckedIOException;
32 import java.nio.ByteBuffer;
33 import java.nio.file.Path;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.EnumSet;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Objects;
43 import java.util.Optional;
44 import java.util.Set;
45 import java.util.function.Supplier;
46 import java.util.stream.Collectors;
47 import java.util.stream.Stream;
48
49 import static jdk.internal.module.Checks.*;
50 import static java.util.Objects.*;
51
52 import jdk.internal.module.Checks;
53 import jdk.internal.module.ModuleInfo;
54
55
56 /**
57 * A module descriptor.
58 *
59 * <p> A {@code ModuleDescriptor} is typically created from the binary form
60 * of a module declaration. Alternatively, the {@link ModuleDescriptor.Builder}
61 * class can be used to create a {@code ModuleDescriptor} from its components.
62 * The {@link #module module}, {@link #openModule openModule}, and {@link
63 * #automaticModule automaticModule} methods create builders for building
64 * different kinds of modules. </p>
65 *
66 * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
67 * multiple concurrent threads.</p>
68 *
69 * @since 9
70 * @see java.lang.reflect.Module
71 */
72
73 public class ModuleDescriptor
104 * but is optional in the dynamic phase, during execution.
105 */
106 STATIC,
107
108 /**
109 * The dependence was not explicitly or implicitly declared in the
110 * source of the module declaration.
111 */
112 SYNTHETIC,
113
114 /**
115 * The dependence was implicitly declared in the source of the module
116 * declaration.
117 */
118 MANDATED;
119
120 }
121
122 private final Set<Modifier> mods;
123 private final String name;
124 private final Version compiledVersion;
125
126 private Requires(Set<Modifier> ms, String mn, Version v) {
127 if (ms.isEmpty()) {
128 ms = Collections.emptySet();
129 } else {
130 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
131 }
132 this.mods = ms;
133 this.name = mn;
134 this.compiledVersion = v;
135 }
136
137 private Requires(Set<Modifier> ms, String mn, Version v, boolean unused) {
138 this.mods = ms;
139 this.name = mn;
140 this.compiledVersion = v;
141 }
142
143 /**
144 * Returns the set of modifiers.
145 *
146 * @return A possibly-empty unmodifiable set of modifiers
147 */
148 public Set<Modifier> modifiers() {
149 return mods;
150 }
151
152 /**
153 * Return the module name.
154 *
155 * @return The module name
156 */
157 public String name() {
158 return name;
159 }
160
161 /**
162 * Returns the version of the module if recorded at compile-time.
163 *
164 * @return The version of the module if recorded at compile-time
165 */
166 public Optional<Version> compiledVersion() {
167 return Optional.ofNullable(compiledVersion);
168 }
169
170 /**
171 * Compares this module dependence to another.
172 *
173 * <p> Two {@code Requires} objects are compared by comparing their
174 * module name lexicographically. Where the module names are equal then
175 * the sets of modifiers are compared based on a value computed from the
176 * ordinal of each modifier. Where the module names are equal and the
177 * set of modifiers are equal then the version of the modules recorded
178 * at compile-time are compared. When comparing the versions recorded
179 * at compile-time then a dependence that has a recorded version is
180 * considered to succeed a dependence that does not have a recorded
181 * version. </p>
182 *
183 * @return A negative integer, zero, or a positive integer if this module
184 * dependence is less than, equal to, or greater than the given
185 * module dependence
186 */
187 @Override
188 public int compareTo(Requires that) {
189 int c = this.name().compareTo(that.name());
190 if (c != 0)
191 return c;
192
193 // modifiers
194 c = Long.compare(this.modsValue(), that.modsValue());
195 if (c != 0)
196 return c;
197
198 // compiledVersion
199 if (this.compiledVersion != null) {
200 if (that.compiledVersion != null)
201 c = this.compiledVersion.compareTo(that.compiledVersion);
202 else
203 c = 1;
204 } else {
205 if (that.compiledVersion != null)
206 c = -1;
207 }
208
209 return c;
210 }
211
212 /**
213 * Return a value for the modifiers to allow sets of modifiers to be
214 * compared.
215 */
216 private long modsValue() {
217 long value = 0;
218 for (Modifier m : mods) {
219 value += 1 << m.ordinal();
220 }
221 return value;
222 }
223
224 /**
225 * Tests this module dependence for equality with the given object.
226 *
227 * <p> If the given object is not a {@code Requires} then this method
228 * returns {@code false}. Two module dependence objects are equal if
229 * the module names are equal, set of modifiers are equal, and the
230 * compiled version of both modules is equal or not recorded for
231 * both modules. </p>
232 *
233 * <p> This method satisfies the general contract of the {@link
234 * java.lang.Object#equals(Object) Object.equals} method. </p>
235 *
236 * @param ob
237 * the object to which this object is to be compared
238 *
239 * @return {@code true} if, and only if, the given object is a module
240 * dependence that is equal to this module dependence
241 */
242 @Override
243 public boolean equals(Object ob) {
244 if (!(ob instanceof Requires))
245 return false;
246 Requires that = (Requires)ob;
247 return name.equals(that.name) && mods.equals(that.mods)
248 && Objects.equals(compiledVersion, that.compiledVersion);
249 }
250
251 /**
252 * Computes a hash code for this module dependence.
253 *
254 * <p> The hash code is based upon the module name, modifiers, and the
255 * module version if recorded at compile time. It satisfies the general
256 * contract of the {@link Object#hashCode Object.hashCode} method. </p>
257 *
258 * @return The hash-code value for this module dependence
259 */
260 @Override
261 public int hashCode() {
262 int hash = name.hashCode() * 43 + mods.hashCode();
263 if (compiledVersion != null)
264 hash = hash * 43 + compiledVersion.hashCode();
265 return hash;
266 }
267
268 /**
269 * Returns a string describing module dependence.
270 *
271 * @return A string describing module dependence
272 */
273 @Override
274 public String toString() {
275 String what;
276 if (compiledVersion != null) {
277 what = name() + " (@" + compiledVersion + ")";
278 } else {
279 what = name();
280 }
281 return ModuleDescriptor.toString(mods, what);
282 }
283 }
284
285
286
287 /**
288 * <p> A module export, may be qualified or unqualified. </p>
289 *
290 * @see ModuleDescriptor#exports()
291 * @since 9
292 */
293
294 public final static class Exports {
295
296 /**
297 * A modifier on a module export.
298 *
299 * @since 9
300 */
301 public static enum Modifier {
993 * @return The hash-code value for this module version
994 */
995 @Override
996 public int hashCode() {
997 return version.hashCode();
998 }
999
1000 /**
1001 * Returns the string from which this version was parsed.
1002 *
1003 * @return The string from which this version was parsed.
1004 */
1005 @Override
1006 public String toString() {
1007 return version;
1008 }
1009
1010 }
1011
1012
1013 private final String name;
1014 private final Version version;
1015 private final boolean open;
1016
1017 // Indicates if synthesised for a JAR file found on the module path
1018 private final boolean automatic;
1019
1020 // Not generated from a module-info.java
1021 private final boolean synthetic;
1022
1023 private final Set<Requires> requires;
1024 private final Set<Exports> exports;
1025 private final Set<Opens> opens;
1026 private final Set<String> uses;
1027 private final Set<Provides> provides;
1028
1029 // Added post-compilation by tools
1030 private final Set<String> packages;
1031 private final String mainClass;
1032 private final String osName;
1033 private final String osArch;
1034 private final String osVersion;
1035
1036
1037 private ModuleDescriptor(String name,
1038 Version version,
1039 boolean open,
1040 boolean automatic,
1041 boolean synthetic,
1042 Set<Requires> requires,
1043 Set<Exports> exports,
1044 Set<Opens> opens,
1045 Set<String> uses,
1046 Set<Provides> provides,
1047 Set<String> packages,
1048 String mainClass,
1049 String osName,
1050 String osArch,
1051 String osVersion)
1052 {
1053 this.name = name;
1054 this.version = version;
1055 this.open = open;
1056 this.automatic = automatic;
1057 this.synthetic = synthetic;
1058
1059 assert (requires.stream().map(Requires::name).distinct().count()
1060 == requires.size());
1061 this.requires = emptyOrUnmodifiableSet(requires);
1062 this.exports = emptyOrUnmodifiableSet(exports);
1063 this.opens = emptyOrUnmodifiableSet(opens);
1064 this.uses = emptyOrUnmodifiableSet(uses);
1065 this.provides = emptyOrUnmodifiableSet(provides);
1066
1067 this.packages = emptyOrUnmodifiableSet(packages);
1068 this.mainClass = mainClass;
1069 this.osName = osName;
1070 this.osArch = osArch;
1071 this.osVersion = osVersion;
1072 }
1073
1074 /**
1075 * Clones the given module descriptor with an augmented set of packages
1076 */
1077 ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) {
1078 this.name = md.name;
1079 this.version = md.version;
1080 this.open = md.open;
1081 this.automatic = md.automatic;
1082 this.synthetic = md.synthetic;
1083
1084 this.requires = md.requires;
1085 this.exports = md.exports;
1086 this.opens = md.opens;
1087 this.uses = md.uses;
1088 this.provides = md.provides;
1089
1090 Set<String> packages = new HashSet<>(md.packages);
1091 packages.addAll(pkgs);
1092 this.packages = emptyOrUnmodifiableSet(packages);
1093
1094 this.mainClass = md.mainClass;
1095 this.osName = md.osName;
1096 this.osArch = md.osArch;
1097 this.osVersion = md.osVersion;
1098 }
1099
1100 /**
1101 * Creates a module descriptor from its components.
1102 * The arguments are pre-validated and sets are unmodifiable sets.
1103 */
1104 ModuleDescriptor(String name,
1105 Version version,
1106 boolean open,
1107 boolean automatic,
1108 boolean synthetic,
1109 Set<Requires> requires,
1110 Set<Exports> exports,
1111 Set<Opens> opens,
1112 Set<String> uses,
1113 Set<Provides> provides,
1114 Set<String> packages,
1115 String mainClass,
1116 String osName,
1117 String osArch,
1118 String osVersion,
1119 int hashCode,
1120 boolean unused) {
1121 this.name = name;
1122 this.version = version;
1123 this.open = open;
1124 this.automatic = automatic;
1125 this.synthetic = synthetic;
1126 this.requires = requires;
1127 this.exports = exports;
1128 this.opens = opens;
1129 this.uses = uses;
1130 this.provides = provides;
1131 this.packages = packages;
1132 this.mainClass = mainClass;
1133 this.osName = osName;
1134 this.osArch = osArch;
1135 this.osVersion = osVersion;
1136 this.hash = hashCode;
1137 }
1138
1139 /**
1140 * <p> The module name. </p>
1141 *
1142 * @return The module name
1143 */
1144 public String name() {
1145 return name;
1146 }
1147
1148 /**
1149 * <p> Returns {@code true} if this is an open module. </p>
1150 *
1151 * <p> An open module does not declare any open packages (the {@link #opens()
1152 * opens} method returns an empty set) but the resulting module is treated
1153 * as if all packages are open. </p>
1154 *
1155 * @return {@code true} if this is an open module
1301 /**
1302 * Returns the operating system version if this module is operating
1303 * system version specific.
1304 *
1305 * @return The operating system version or an empty {@code Optional}
1306 * if this module is not operating system version specific
1307 */
1308 public Optional<String> osVersion() {
1309 return Optional.ofNullable(osVersion);
1310 }
1311
1312 /**
1313 * Returns the names of all packages in this module.
1314 *
1315 * @return A possibly-empty unmodifiable set of all packages in the module
1316 */
1317 public Set<String> packages() {
1318 return packages;
1319 }
1320
1321
1322 /**
1323 * A builder used for building {@link ModuleDescriptor} objects.
1324 *
1325 * <p> {@code ModuleDescriptor} defines the {@link #module module}, {@link
1326 * #openModule openModule}, and {@link #automaticModule automaticModule}
1327 * methods to create builders for building different kinds of modules. </p>
1328 *
1329 * <p> Example usage: </p>
1330 * <pre>{@code ModuleDescriptor descriptor = ModuleDescriptor.module("m1")
1331 * .exports("p")
1332 * .requires("m2")
1333 * .build();
1334 * }</pre>
1335 *
1336 * @apiNote A {@code Builder} checks the components and invariants as
1337 * components are added to the builder. The rational for this is to detect
1338 * errors as early as possible and not defer all validation to the
1339 * {@link #build build} method. A {@code Builder} cannot be used to create
1340 * a {@link ModuleDescriptor#isSynthetic() synthetic} module.
1341 *
1342 * @since 9
1343 */
1344 public static final class Builder {
1345 final String name;
1346 final boolean strict; // true if module names are checked
1347 final boolean open;
1348 final boolean synthetic;
1349 boolean automatic;
1350 final Map<String, Requires> requires = new HashMap<>();
1351 final Map<String, Exports> exports = new HashMap<>();
1352 final Map<String, Opens> opens = new HashMap<>();
1353 final Set<String> concealedPackages = new HashSet<>();
1354 final Set<String> uses = new HashSet<>();
1355 final Map<String, Provides> provides = new HashMap<>();
1356 Version version;
1357 String osName;
1358 String osArch;
1359 String osVersion;
1360 String mainClass;
1361
1362 /**
1363 * Initializes a new builder with the given module name.
1364 *
1365 * @param strict
1366 * Indicates whether module names are checked or not
1367 */
1368 Builder(String name, boolean strict, boolean open, boolean synthetic) {
1369 this.name = (strict) ? requireModuleName(name) : name;
1370 this.strict = strict;
1371 this.open = open;
1372 this.synthetic = synthetic;
1373 }
1374
1375 /* package */ Builder automatic(boolean automatic) {
1376 this.automatic = automatic;
1377 return this;
1378 }
1379
1380 /**
1381 * Returns the set of packages that are exported (unconditionally or
1382 * unconditionally).
1383 */
1384 /* package */ Set<String> exportedPackages() {
1385 return exports.keySet();
1386 }
1387
1388 /**
1389 * Returns the set of packages that are opened (unconditionally or
1390 * unconditionally).
1391 */
1392 /* package */Set<String> openPackages() {
1393 return opens.keySet();
1394 }
1395
1396 /**
1397 * Adds a dependence on a module.
1398 *
1399 * @param req
1400 * The dependence
1401 *
1402 * @return This builder
1403 *
1404 * @throws IllegalArgumentException
1405 * If the dependence is on the module that this builder was
1406 * initialized to build
1407 * @throws IllegalStateException
1408 * If the dependence on the module has already been declared
1409 */
1410 public Builder requires(Requires req) {
1411 String mn = req.name();
1412 if (name.equals(mn))
1413 throw new IllegalArgumentException("Dependence on self");
1414 if (requires.containsKey(mn))
1415 throw new IllegalStateException("Dependence upon " + mn
1416 + " already declared");
1417 requires.put(mn, req);
1418 return this;
1419 }
1420
1421 /**
1422 * Adds a dependence on a module with the given (and possibly empty)
1423 * set of modifiers. The dependence includes the version of the
1424 * module that that was recorded at compile-time.
1425 *
1426 * @param ms
1427 * The set of modifiers
1428 * @param mn
1429 * The module name
1430 * @param compiledVersion
1431 * The version of the module recorded at compile-time
1432 *
1433 * @return This builder
1434 *
1435 * @throws IllegalArgumentException
1436 * If the module name is {@code null}, is not a legal Java
1437 * identifier, or is equal to the module name that this builder
1438 * was initialized to build
1439 * @throws IllegalStateException
1440 * If the dependence on the module has already been declared
1441 */
1442 public Builder requires(Set<Requires.Modifier> ms,
1443 String mn,
1444 Version compiledVersion) {
1445 Objects.requireNonNull(compiledVersion);
1446 if (strict)
1447 mn = requireModuleName(mn);
1448 return requires(new Requires(ms, mn, compiledVersion));
1449 }
1450
1451 /**
1452 * Adds a dependence on a module with the given (and possibly empty)
1453 * set of modifiers.
1454 *
1455 * @param ms
1456 * The set of modifiers
1457 * @param mn
1458 * The module name
1459 *
1460 * @return This builder
1461 *
1462 * @throws IllegalArgumentException
1463 * If the module name is {@code null}, is not a legal Java
1464 * identifier, or is equal to the module name that this builder
1465 * was initialized to build
1466 * @throws IllegalStateException
1467 * If the dependence on the module has already been declared
1468 */
1469 public Builder requires(Set<Requires.Modifier> ms, String mn) {
1470 if (strict)
1471 mn = requireModuleName(mn);
1472 return requires(new Requires(ms, mn, null));
1473 }
1474
1475 /**
1476 * Adds a dependence on a module with an empty set of modifiers.
1477 *
1478 * @param mn
1479 * The module name
1480 *
1481 * @return This builder
1482 *
1483 * @throws IllegalArgumentException
1484 * If the module name is {@code null}, is not a legal Java
1485 * identifier, or is equal to the module name that this builder
1486 * was initialized to build
1487 * @throws IllegalStateException
1488 * If the dependence on the module has already been declared
1489 */
1490 public Builder requires(String mn) {
1491 return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
1492 }
1749 /**
1750 * Adds an <em>opens</em> directive to open a package.
1751 *
1752 * @param pn
1753 * The package name
1754 *
1755 * @return This builder
1756 *
1757 * @throws IllegalArgumentException
1758 * If the package name is {@code null} or is not a legal Java
1759 * identifier
1760 * @throws IllegalStateException
1761 * If the package is already declared as a package with the
1762 * {@link #contains contains} method, the package is already
1763 * declared as open, or this is a builder for an open module
1764 */
1765 public Builder opens(String pn) {
1766 return opens(Collections.emptySet(), pn);
1767 }
1768
1769 /**
1770 * Adds a service dependence.
1771 *
1772 * @param service
1773 * The service type
1774 *
1775 * @return This builder
1776 *
1777 * @throws IllegalArgumentException
1778 * If the service type is {@code null} or is not a legal Java
1779 * identifier
1780 * @throws IllegalStateException
1781 * If a dependency on the service type has already been declared
1782 */
1783 public Builder uses(String service) {
1784 if (uses.contains(requireServiceTypeName(service)))
1785 throw new IllegalStateException("Dependence upon service "
1786 + service + " already declared");
1787 uses.add(service);
1788 return this;
1822 * @throws IllegalArgumentException
1823 * If the service type or any of the provider class names is
1824 * {@code null} or is not a legal Java identifier, or the list
1825 * of provider class names is empty
1826 * @throws IllegalStateException
1827 * If the providers for the service type have already been
1828 * declared
1829 */
1830 public Builder provides(String service, List<String> providers) {
1831 if (provides.containsKey(service))
1832 throw new IllegalStateException("Providers of service "
1833 + service + " already declared by " + name);
1834
1835 Provides p = new Provides(requireServiceTypeName(service), providers);
1836
1837 // check providers after the set has been copied.
1838 List<String> providerNames = p.providers();
1839 if (providerNames.isEmpty())
1840 throw new IllegalArgumentException("Empty providers set");
1841 providerNames.forEach(Checks::requireServiceProviderName);
1842 provides.put(service, p);
1843 return this;
1844 }
1845
1846 /**
1847 * Provides an implementation of a service.
1848 *
1849 * @param service
1850 * The service type
1851 * @param provider
1852 * The provider or provider factory class name
1853 *
1854 * @return This builder
1855 *
1856 * @throws IllegalArgumentException
1857 * If the service type or the provider class name is {@code
1858 * null} or is not a legal Java identifier
1859 * @throws IllegalStateException
1860 * If the providers for the service type have already been
1861 * declared
1946 * If {@code v} is null or cannot be parsed as a version string
1947 *
1948 * @see Version#parse(String)
1949 */
1950 public Builder version(String v) {
1951 return version(Version.parse(v));
1952 }
1953
1954 /**
1955 * Sets the module main class.
1956 *
1957 * @param mc
1958 * The module main class
1959 *
1960 * @return This builder
1961 *
1962 * @throws IllegalArgumentException
1963 * If {@code mainClass} is null or is not a legal Java identifier
1964 */
1965 public Builder mainClass(String mc) {
1966 mainClass = requireBinaryName("main class name", mc);
1967 return this;
1968 }
1969
1970 /**
1971 * Sets the operating system name.
1972 *
1973 * @param name
1974 * The operating system name
1975 *
1976 * @return This builder
1977 *
1978 * @throws IllegalArgumentException
1979 * If {@code name} is null or the empty String
1980 */
1981 public Builder osName(String name) {
1982 if (name == null || name.isEmpty())
1983 throw new IllegalArgumentException("OS name is null or empty");
1984 osName = name;
1985 return this;
1986 }
2004 }
2005
2006 /**
2007 * Sets the operating system version.
2008 *
2009 * @param version
2010 * The operating system version
2011 *
2012 * @return This builder
2013 *
2014 * @throws IllegalArgumentException
2015 * If {@code name} is null or the empty String
2016 */
2017 public Builder osVersion(String version) {
2018 if (version == null || version.isEmpty())
2019 throw new IllegalArgumentException("OS version is null or empty");
2020 osVersion = version;
2021 return this;
2022 }
2023
2024 /**
2025 * Builds and returns a {@code ModuleDescriptor} from its components.
2026 *
2027 * @return The module descriptor
2028 */
2029 public ModuleDescriptor build() {
2030 Set<Requires> requires = new HashSet<>(this.requires.values());
2031
2032 Set<String> packages = new HashSet<>();
2033 packages.addAll(exports.keySet());
2034 packages.addAll(opens.keySet());
2035 packages.addAll(concealedPackages);
2036
2037 Set<Exports> exports = new HashSet<>(this.exports.values());
2038 Set<Opens> opens = new HashSet<>(this.opens.values());
2039
2040 Set<Provides> provides = new HashSet<>(this.provides.values());
2041
2042 return new ModuleDescriptor(name,
2043 version,
2044 open,
2045 automatic,
2046 synthetic,
2047 requires,
2048 exports,
2049 opens,
2050 uses,
2051 provides,
2052 packages,
2053 mainClass,
2054 osName,
2055 osArch,
2056 osVersion);
2057 }
2058
2059 }
2060
2061 /**
2062 * Compares this module descriptor to another.
2063 *
2064 * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
2065 * module name lexicographically. Where the module names are equal then
2066 * the versions, if present, are compared. </p>
2067 *
2068 * @apiNote For now, the natural ordering is not consistent with equals.
2069 * If two module descriptors have equal module names, equal versions if
2070 * present, but their corresponding components are not equal, then they
2071 * will be considered equal by this method.
2072 *
2073 * @param that
2074 * The object to which this module descriptor is to be compared
2075 *
2076 * @return A negative integer, zero, or a positive integer if this module
2111 public boolean equals(Object ob) {
2112 if (ob == this)
2113 return true;
2114 if (!(ob instanceof ModuleDescriptor))
2115 return false;
2116 ModuleDescriptor that = (ModuleDescriptor)ob;
2117 return (name.equals(that.name)
2118 && open == that.open
2119 && automatic == that.automatic
2120 && synthetic == that.synthetic
2121 && requires.equals(that.requires)
2122 && exports.equals(that.exports)
2123 && opens.equals(that.opens)
2124 && uses.equals(that.uses)
2125 && provides.equals(that.provides)
2126 && Objects.equals(version, that.version)
2127 && Objects.equals(mainClass, that.mainClass)
2128 && Objects.equals(osName, that.osName)
2129 && Objects.equals(osArch, that.osArch)
2130 && Objects.equals(osVersion, that.osVersion)
2131 && Objects.equals(packages, that.packages));
2132 }
2133
2134 private transient int hash; // cached hash code
2135
2136 /**
2137 * Computes a hash code for this module descriptor.
2138 *
2139 * <p> The hash code is based upon the components of the module descriptor,
2140 * and satisfies the general contract of the {@link Object#hashCode
2141 * Object.hashCode} method. </p>
2142 *
2143 * @return The hash-code value for this module descriptor
2144 */
2145 @Override
2146 public int hashCode() {
2147 int hc = hash;
2148 if (hc == 0) {
2149 hc = name.hashCode();
2150 hc = hc * 43 + Boolean.hashCode(open);
2151 hc = hc * 43 + Boolean.hashCode(automatic);
2152 hc = hc * 43 + Boolean.hashCode(synthetic);
2153 hc = hc * 43 + requires.hashCode();
2154 hc = hc * 43 + exports.hashCode();
2155 hc = hc * 43 + opens.hashCode();
2156 hc = hc * 43 + uses.hashCode();
2157 hc = hc * 43 + provides.hashCode();
2158 hc = hc * 43 + Objects.hashCode(version);
2159 hc = hc * 43 + Objects.hashCode(mainClass);
2160 hc = hc * 43 + Objects.hashCode(osName);
2161 hc = hc * 43 + Objects.hashCode(osArch);
2162 hc = hc * 43 + Objects.hashCode(osVersion);
2163 hc = hc * 43 + Objects.hashCode(packages);
2164 if (hc == 0)
2165 hc = -1;
2166 hash = hc;
2167 }
2168 return hc;
2169 }
2170
2171 /**
2172 * Returns a string describing this descriptor.
2173 *
2174 * @return A string describing this descriptor
2175 */
2176 @Override
2177 public String toString() {
2178 StringBuilder sb = new StringBuilder();
2179
2180 if (isOpen())
2181 sb.append("open ");
2182 sb.append("module { name: ").append(toNameAndVersion());
2183 if (!requires.isEmpty())
2184 sb.append(", ").append(requires);
2185 if (!uses.isEmpty())
2186 sb.append(", uses: ").append(uses);
2187 if (!exports.isEmpty())
2188 sb.append(", exports: ").append(exports);
2189 if (!opens.isEmpty())
2190 sb.append(", opens: ").append(opens);
2191 if (!provides.isEmpty()) {
2192 sb.append(", provides: ").append(provides);
2193 }
2194 sb.append(" }");
2195 return sb.toString();
2196 }
2197
2198
2199 /**
2200 * Instantiates a builder to build a module descriptor.
2201 *
2202 * @param name
2203 * The module name
2204 *
2205 * @return A new builder
2206 *
2207 * @throws IllegalArgumentException
2208 * If the module name is {@code null} or is not a legal Java
2209 * identifier
2210 */
2211 public static Builder module(String name) {
2212 return new Builder(name, true, false, false);
2213 }
2214
2215 /**
2216 * Instantiates a builder to build a module descriptor for an open module.
2217 * An open module does not declare any open packages but the resulting
2218 * module is treated as if all packages are open.
2219 *
2220 * <p> As an example, the following creates a module descriptor for an open
2221 * name "{@code m}" containing two packages, one of which is exported. </p>
2222 * <pre>{@code
2223 * ModuleDescriptor descriptor = ModuleDescriptor.openModule("m")
2224 * .requires("java.base")
2225 * .exports("p")
2226 * .contains("q")
2227 * .build();
2228 * }</pre>
2229 *
2230 * @param name
2231 * The module name
2232 *
2233 * @return A new builder that builds an open module
2234 *
2235 * @throws IllegalArgumentException
2236 * If the module name is {@code null} or is not a legal Java
2237 * identifier
2238 */
2239 public static Builder openModule(String name) {
2240 return new Builder(name, true, true, false);
2241 }
2242
2243 /**
2244 * Instantiates a builder to build a module descriptor for an automatic
2245 * module. Automatic modules receive special treatment during resolution
2246 * (see {@link Configuration}) so that they read all other modules. When
2247 * Instantiated in the Java virtual machine as a {@link java.lang.reflect.Module}
2248 * then the Module reads every unnamed module in the Java virtual machine.
2249 *
2250 * @param name
2251 * The module name
2252 *
2253 * @return A new builder that builds an automatic module
2254 *
2255 * @throws IllegalArgumentException
2256 * If the module name is {@code null} or is not a legal Java
2257 * identifier
2258 *
2259 * @see ModuleFinder#of(Path[])
2260 */
2261 public static Builder automaticModule(String name) {
2262 return new Builder(name, true, false, false).automatic(true);
2263 }
2264
2265
2266 /**
2267 * Reads the binary form of a module declaration from an input stream
2268 * as a module descriptor.
2269 *
2270 * <p> If the descriptor encoded in the input stream does not indicate a
2271 * set of packages in the module then the {@code packageFinder} will be
2272 * invoked. If the {@code packageFinder} throws an {@link UncheckedIOException}
2273 * then {@link IOException} cause will be re-thrown. </p>
2274 *
2275 * <p> If there are bytes following the module descriptor then it is
2276 * implementation specific as to whether those bytes are read, ignored,
2277 * or reported as an {@code InvalidModuleDescriptorException}. If this
2278 * method fails with an {@code InvalidModuleDescriptorException} or {@code
2279 * IOException} then it may do so after some, but not all, bytes have
2280 * been read from the input stream. It is strongly recommended that the
2281 * stream be promptly closed and discarded if an exception occurs. </p>
2282 *
2284 * module descriptors from legacy module-artifact formats that do not
2285 * record the set of packages in the descriptor itself.
2286 *
2287 * @param in
2288 * The input stream
2289 * @param packageFinder
2290 * A supplier that can produce the set of packages
2291 *
2292 * @return The module descriptor
2293 *
2294 * @throws InvalidModuleDescriptorException
2295 * If an invalid module descriptor is detected
2296 * @throws IOException
2297 * If an I/O error occurs reading from the input stream or {@code
2298 * UncheckedIOException} is thrown by the package finder
2299 */
2300 public static ModuleDescriptor read(InputStream in,
2301 Supplier<Set<String>> packageFinder)
2302 throws IOException
2303 {
2304 return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
2305 }
2306
2307 /**
2308 * Reads the binary form of a module declaration from an input stream
2309 * as a module descriptor.
2310 *
2311 * @param in
2312 * The input stream
2313 *
2314 * @return The module descriptor
2315 *
2316 * @throws InvalidModuleDescriptorException
2317 * If an invalid module descriptor is detected
2318 * @throws IOException
2319 * If an I/O error occurs reading from the input stream
2320 */
2321 public static ModuleDescriptor read(InputStream in) throws IOException {
2322 return ModuleInfo.read(in, null).descriptor();
2323 }
2324
2325 /**
2326 * Reads the binary form of a module declaration from a byte buffer
2327 * as a module descriptor.
2328 *
2329 * <p> If the descriptor encoded in the byte buffer does not indicate a
2330 * set of packages then the {@code packageFinder} will be invoked. </p>
2331 *
2332 * <p> The module descriptor is read from the buffer stating at index
2333 * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
2334 * position} when this method is invoked. Upon return the buffer's position
2335 * will be equal to {@code p + n} where {@code n} is the number of bytes
2336 * read from the buffer. </p>
2337 *
2338 * <p> If there are bytes following the module descriptor then it is
2339 * implementation specific as to whether those bytes are read, ignored,
2340 * or reported as an {@code InvalidModuleDescriptorException}. If this
2341 * method fails with an {@code InvalidModuleDescriptorException} then it
2342 * may do so after some, but not all, bytes have been read. </p>
2343 *
2344 * @apiNote The {@code packageFinder} parameter is for use when reading
2345 * module descriptors from legacy module-artifact formats that do not
2346 * record the set of packages in the descriptor itself.
2347 *
2348 * @param bb
2349 * The byte buffer
2350 * @param packageFinder
2351 * A supplier that can produce the set of packages
2352 *
2353 * @return The module descriptor
2354 *
2355 * @throws InvalidModuleDescriptorException
2356 * If an invalid module descriptor is detected
2357 */
2358 public static ModuleDescriptor read(ByteBuffer bb,
2359 Supplier<Set<String>> packageFinder)
2360 {
2361 return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
2362 }
2363
2364 /**
2365 * Reads the binary form of a module declaration from a byte buffer
2366 * as a module descriptor.
2367 *
2368 * @param bb
2369 * The byte buffer
2370 *
2371 * @return The module descriptor
2372 *
2373 * @throws InvalidModuleDescriptorException
2374 * If an invalid module descriptor is detected
2375 */
2376 public static ModuleDescriptor read(ByteBuffer bb) {
2377 return ModuleInfo.read(bb, null).descriptor();
2378 }
2379
2380 private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
2381 if (map.isEmpty()) {
2382 return Collections.emptyMap();
2383 } else if (map.size() == 1) {
2384 Map.Entry<K, V> entry = map.entrySet().iterator().next();
2385 return Collections.singletonMap(entry.getKey(), entry.getValue());
2386 } else {
2387 return Collections.unmodifiableMap(map);
2388 }
2389 }
2390
2391 private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) {
2392 if (set.isEmpty()) {
2393 return Collections.emptySet();
2394 } else if (set.size() == 1) {
2395 return Collections.singleton(set.iterator().next());
2396 } else {
2397 return Collections.unmodifiableSet(set);
2398 }
2399 }
2400
2401 /**
2402 * Returns a string containing the given set of modifiers and label.
2403 */
2404 private static <M> String toString(Set<M> mods, String what) {
2405 return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
2406 Stream.of(what)))
2407 .collect(Collectors.joining(" "));
2408 }
2409
2410 static {
2411 /**
2412 * Setup the shared secret to allow code in other packages access
2413 * private package methods in java.lang.module.
2414 */
2415 jdk.internal.misc.SharedSecrets
2416 .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
2417 @Override
2418 public Builder newModuleBuilder(String mn,
2419 boolean strict,
2420 boolean open,
2421 boolean synthetic) {
2422 return new Builder(mn, strict, open, synthetic);
2423 }
2424
2425 @Override
2426 public Set<String> exportedPackages(ModuleDescriptor.Builder builder) {
2427 return builder.exportedPackages();
2428 }
2429
2430 @Override
2431 public Set<String> openPackages(ModuleDescriptor.Builder builder) {
2432 return builder.openPackages();
2433 }
2434
2435 @Override
2436 public Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v) {
2437 return new Requires(ms, mn, v, true);
2438 }
2439
2440 @Override
2441 public Exports newExports(Set<Exports.Modifier> ms, String source) {
2442 return new Exports(ms, source, Collections.emptySet(), true);
2443 }
2444
2445 @Override
2446 public Exports newExports(Set<Exports.Modifier> ms,
2447 String source,
2448 Set<String> targets) {
2449 return new Exports(ms, source, targets, true);
2450 }
2451
2452 @Override
2453 public Opens newOpens(Set<Opens.Modifier> ms,
2454 String source,
2455 Set<String> targets) {
2456 return new Opens(ms, source, targets, true);
2457 }
2462 }
2463
2464 @Override
2465 public Provides newProvides(String service, List<String> providers) {
2466 return new Provides(service, providers, true);
2467 }
2468
2469 @Override
2470 public Version newVersion(String v) {
2471 return new Version(v);
2472 }
2473
2474 @Override
2475 public ModuleDescriptor newModuleDescriptor(ModuleDescriptor md,
2476 Set<String> pkgs) {
2477 return new ModuleDescriptor(md, pkgs);
2478 }
2479
2480 @Override
2481 public ModuleDescriptor newModuleDescriptor(String name,
2482 Version version,
2483 boolean open,
2484 boolean automatic,
2485 boolean synthetic,
2486 Set<Requires> requires,
2487 Set<Exports> exports,
2488 Set<Opens> opens,
2489 Set<String> uses,
2490 Set<Provides> provides,
2491 Set<String> packages,
2492 String mainClass,
2493 String osName,
2494 String osArch,
2495 String osVersion,
2496 int hashCode) {
2497 return new ModuleDescriptor(name,
2498 version,
2499 open,
2500 automatic,
2501 synthetic,
2502 requires,
2503 exports,
2504 opens,
2505 uses,
2506 provides,
2507 packages,
2508 mainClass,
2509 osName,
2510 osArch,
2511 osVersion,
2512 hashCode,
2513 false);
2514 }
2515
2516 @Override
2517 public Configuration resolveRequiresAndUses(ModuleFinder finder,
2518 Collection<String> roots,
2519 boolean check,
2520 PrintStream traceOutput)
2521 {
2522 return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
2523 }
2524 });
2525 }
2526
2527 }
|