1 /*
2 * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
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
74 implements Comparable<ModuleDescriptor>
75 {
76
77 /**
78 * <p> A dependence upon a module </p>
79 *
80 * @see ModuleDescriptor#requires()
81 * @since 9
82 */
83
84 public final static class Requires
85 implements Comparable<Requires>
86 {
87
88 /**
89 * A modifier on a module dependence.
90 *
91 * @since 9
92 */
93 public static enum Modifier {
94
95 /**
96 * The dependence causes any module which depends on the <i>current
97 * module</i> to have an implicitly declared dependence on the module
98 * named by the {@code Requires}.
99 */
100 TRANSITIVE,
101
102 /**
103 * The dependence is mandatory in the static phase, during compilation,
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 */
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 */
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 {
302
303 /**
304 * The export was not explicitly or implicitly declared in the
305 * source of the module declaration.
306 */
307 SYNTHETIC,
308
309 /**
310 * The export was implicitly declared in the source of the module
311 * declaration.
312 */
313 MANDATED;
314
315 }
316
317 private final Set<Modifier> mods;
318 private final String source;
319 private final Set<String> targets; // empty if unqualified export
364 *
365 * @return The package name
366 */
367 public String source() {
368 return source;
369 }
370
371 /**
372 * For a qualified export, returns the non-empty and immutable set
373 * of the module names to which the package is exported. For an
374 * unqualified export, returns an empty set.
375 *
376 * @return The set of target module names or for an unqualified
377 * export, an empty set
378 */
379 public Set<String> targets() {
380 return targets;
381 }
382
383 /**
384 * Computes a hash code for this module export.
385 *
386 * <p> The hash code is based upon the modifiers, the package name,
387 * and for a qualified export, the set of modules names to which the
388 * package is exported. It satisfies the general contract of the
389 * {@link Object#hashCode Object.hashCode} method.
390 *
391 * @return The hash-code value for this module export
392 */
393 @Override
394 public int hashCode() {
395 int hash = mods.hashCode();
396 hash = hash * 43 + source.hashCode();
397 return hash * 43 + targets.hashCode();
398 }
399
400 /**
401 * Tests this module export for equality with the given object.
402 *
403 * <p> If the given object is not an {@code Exports} then this method
408 * <p> This method satisfies the general contract of the {@link
409 * java.lang.Object#equals(Object) Object.equals} method. </p>
410 *
411 * @param ob
412 * the object to which this object is to be compared
413 *
414 * @return {@code true} if, and only if, the given object is a module
415 * dependence that is equal to this module dependence
416 */
417 @Override
418 public boolean equals(Object ob) {
419 if (!(ob instanceof Exports))
420 return false;
421 Exports other = (Exports)ob;
422 return Objects.equals(this.mods, other.mods)
423 && Objects.equals(this.source, other.source)
424 && Objects.equals(this.targets, other.targets);
425 }
426
427 /**
428 * Returns a string describing module export.
429 *
430 * @return A string describing module export
431 */
432 @Override
433 public String toString() {
434 String s = ModuleDescriptor.toString(mods, source);
435 if (targets.isEmpty())
436 return s;
437 else
438 return s + " to " + targets;
439 }
440 }
441
442
443 /**
444 * <p> Represents a module <em>opens</em> directive, may be qualified or
445 * unqualified. </p>
446 *
447 * <p> The <em>opens</em> directive in a module declaration declares a
448 * package to be open to allow all types in the package, and all their
449 * members, not just public types and their public members to be reflected
450 * on by APIs that support private access or a way to bypass or suppress
451 * default Java language access control checks. </p>
452 *
453 * @see ModuleDescriptor#opens()
454 * @since 9
455 */
456
457 public final static class Opens {
458
459 /**
460 * A modifier on a module <em>opens</em> directive.
461 *
462 * @since 9
463 */
464 public static enum Modifier {
465
466 /**
467 * The opens was not explicitly or implicitly declared in the
468 * source of the module declaration.
469 */
470 SYNTHETIC,
471
472 /**
473 * The opens was implicitly declared in the source of the module
474 * declaration.
475 */
476 MANDATED;
477
478 }
479
480 private final Set<Modifier> mods;
481 private final String source;
482 private final Set<String> targets; // empty if unqualified export
483
484 /**
485 * Constructs an Opens
486 */
487 private Opens(Set<Modifier> ms, String source, Set<String> targets) {
488 if (ms.isEmpty()) {
489 ms = Collections.emptySet();
490 } else {
491 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
492 }
493 this.mods = ms;
494 this.source = source;
527 *
528 * @return The package name
529 */
530 public String source() {
531 return source;
532 }
533
534 /**
535 * For a qualified opens, returns the non-empty and immutable set
536 * of the module names to which the package is open. For an
537 * unqualified opens, returns an empty set.
538 *
539 * @return The set of target module names or for an unqualified
540 * opens, an empty set
541 */
542 public Set<String> targets() {
543 return targets;
544 }
545
546 /**
547 * Computes a hash code for this module opens.
548 *
549 * <p> The hash code is based upon the modifiers, the package name,
550 * and for a qualified opens, the set of modules names to which the
551 * package is opened. It satisfies the general contract of the
552 * {@link Object#hashCode Object.hashCode} method.
553 *
554 * @return The hash-code value for this module opens
555 */
556 @Override
557 public int hashCode() {
558 int hash = mods.hashCode();
559 hash = hash * 43 + source.hashCode();
560 return hash * 43 + targets.hashCode();
561 }
562
563 /**
564 * Tests this module opens for equality with the given object.
565 *
566 * <p> If the given object is not an {@code Opens} then this method
571 * <p> This method satisfies the general contract of the {@link
572 * java.lang.Object#equals(Object) Object.equals} method. </p>
573 *
574 * @param ob
575 * the object to which this object is to be compared
576 *
577 * @return {@code true} if, and only if, the given object is a module
578 * dependence that is equal to this module dependence
579 */
580 @Override
581 public boolean equals(Object ob) {
582 if (!(ob instanceof Opens))
583 return false;
584 Opens other = (Opens)ob;
585 return Objects.equals(this.mods, other.mods)
586 && Objects.equals(this.source, other.source)
587 && Objects.equals(this.targets, other.targets);
588 }
589
590 /**
591 * Returns a string describing module opens.
592 *
593 * @return A string describing module opens
594 */
595 @Override
596 public String toString() {
597 String s = ModuleDescriptor.toString(mods, source);
598 if (targets.isEmpty())
599 return s;
600 else
601 return s + " to " + targets;
602 }
603 }
604
605
606 /**
607 * <p> A service that a module provides one or more implementations of. </p>
608 *
609 * @see ModuleDescriptor#provides()
610 * @since 9
611 */
612
613 public final static class Provides {
614
615 private final String service;
616 private final List<String> providers;
617
618 private Provides(String service, List<String> providers) {
619 this.service = service;
620 this.providers = Collections.unmodifiableList(providers);
621 }
622
623 private Provides(String service, List<String> providers, boolean unused) {
624 this.service = service;
625 this.providers = providers;
626 }
627
628 /**
629 * Returns the fully qualified class name of the service type.
630 *
631 * @return The fully qualified class name of the service type.
632 */
633 public String service() { return service; }
634
635 /**
636 * Returns the list of the fully qualified class names of the providers
637 * or provider factories.
638 *
639 * @return A non-empty and unmodifiable list of the fully qualified class
640 * names of the providers or provider factories
641 */
642 public List<String> providers() { return providers; }
643
644 /**
645 * Computes a hash code for this provides.
646 *
647 * <p> The hash code is based upon the service type and the set of
648 * providers. It satisfies the general contract of the {@link
649 * Object#hashCode Object.hashCode} method. </p>
650 *
651 * @return The hash-code value for this module provides
652 */
653 @Override
654 public int hashCode() {
655 return service.hashCode() * 43 + providers.hashCode();
656 }
657
658 /**
659 * Tests this provides for equality with the given object.
660 *
661 * <p> If the given object is not a {@code Provides} then this method
662 * returns {@code false}. Two {@code Provides} objects are equal if the
663 * service type is equal and the list of providers is equal. </p>
664 *
682
683 /**
684 * Returns a string describing this provides.
685 *
686 * @return A string describing this provides
687 */
688 @Override
689 public String toString() {
690 return service + " with " + providers;
691 }
692
693 }
694
695
696
697 /**
698 * A module's version string.
699 *
700 * <p> A version string has three components: The version number itself, an
701 * optional pre-release version, and an optional build version. Each
702 * component is sequence of tokens; each token is either a non-negative
703 * integer or a string. Tokens are separated by the punctuation characters
704 * {@code '.'}, {@code '-'}, or {@code '+'}, or by transitions from a
705 * sequence of digits to a sequence of characters that are neither digits
706 * nor punctuation characters, or vice versa.
707 *
708 * <ul>
709 *
710 * <li> The <i>version number</i> is a sequence of tokens separated by
711 * {@code '.'} characters, terminated by the first {@code '-'} or {@code
712 * '+'} character. </li>
713 *
714 * <li> The <i>pre-release version</i> is a sequence of tokens separated
715 * by {@code '.'} or {@code '-'} characters, terminated by the first
716 * {@code '+'} character. </li>
717 *
718 * <li> The <i>build version</i> is a sequence of tokens separated by
719 * {@code '.'}, {@code '-'}, or {@code '+'} characters.
720 *
721 * </ul>
722 *
723 * <p> When comparing two version strings, the elements of their
724 * corresponding components are compared in pointwise fashion. If one
725 * component is longer than the other, but otherwise equal to it, then the
726 * first component is considered the greater of the two; otherwise, if two
727 * corresponding elements are integers then they are compared as such;
728 * otherwise, at least one of the elements is a string, so the other is
729 * converted into a string if it is an integer and the two are compared
730 * lexicographically. Trailing integer elements with the value zero are
731 * ignored.
732 *
733 * <p> Given two version strings, if their version numbers differ then the
734 * result of comparing them is the result of comparing their version
735 * numbers; otherwise, if one of them has a pre-release version but the
736 * other does not then the first is considered to precede the second,
737 * otherwise the result of comparing them is the result of comparing their
738 * pre-release versions; otherwise, the result of comparing them is the
739 * result of comparing their build versions.
740 *
741 * @see ModuleDescriptor#version()
742 * @since 9
743 */
744
745 public final static class Version
746 implements Comparable<Version>
747 {
748
749 private final String version;
750
751 // If Java had disjunctive types then we'd write List<Integer|String> here
752 //
753 private final List<Object> sequence;
754 private final List<Object> pre;
755 private final List<Object> build;
756
757 // Take a numeric token starting at position i
758 // Append it to the given list
759 // Return the index of the first character not taken
760 // Requires: s.charAt(i) is (decimal) numeric
761 //
762 private static int takeNumber(String s, int i, List<Object> acc) {
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
1156 */
1157 public boolean isOpen() {
1158 return open;
1159 }
1160
1161 /**
1162 * <p> Returns {@code true} if this is an automatic module. </p>
1163 *
1164 * <p> An automatic module is defined implicitly rather than explicitly
1165 * and therefore does not have a module declaration. JAR files located on
1166 * the application module path, or by the {@link ModuleFinder} returned by
1167 * {@link ModuleFinder#of(java.nio.file.Path[]) ModuleFinder.of}, are
1168 * treated as automatic modules if they do have not have a module
1169 * declaration. </p>
1170 *
1171 * @return {@code true} if this is an automatic module
1172 */
1173 public boolean isAutomatic() {
1174 return automatic;
1175 }
1176
1177 /**
1178 * <p> Returns {@code true} if this module descriptor was not generated
1179 * from an explicit module declaration ({@code module-info.java})
1180 * or an implicit module declaration (an {@link #isAutomatic() automatic}
1181 * module). </p>
1182 *
1183 * @return {@code true} if this module descriptor was not generated by
1184 * an explicit or implicit module declaration
1185 */
1186 public boolean isSynthetic() {
1187 return synthetic;
1188 }
1189
1190 /**
1191 * <p> The dependences of this module. </p>
1192 *
1193 * @return A possibly-empty unmodifiable set of {@link Requires} objects
1194 */
1195 public Set<Requires> requires() {
1196 return requires;
1197 }
1198
1199 /**
1200 * <p> The module exports. </p>
1201 *
1202 * @return A possibly-empty unmodifiable set of exported packages
1203 */
1204 public Set<Exports> exports() {
1205 return exports;
1206 }
1207
1208 /**
1209 * <p> The module <em>opens</em> directives. </p>
1210 *
1211 * <p> Each {@code Opens} object in the set represents a package (and
1212 * the set of target module names when qualified) where all types in the
1213 * package, and all their members, not just public types and their public
1214 * members, can be reflected on when using APIs that bypass or suppress
1215 * default Java language access control checks. </p>
1216 *
1217 * <p> This method returns an empty set when invoked on {@link #isOpen()
1218 * open} module. </p>
1219 *
1220 * @return A possibly-empty unmodifiable set of open packages
1221 */
1222 public Set<Opens> opens() {
1223 return opens;
1224 }
1225
1226 /**
1227 * <p> The service dependences of this module. </p>
1228 *
1229 * @return A possibly-empty unmodifiable set of the fully qualified class
1230 * names of the service types used
1231 */
1232 public Set<String> uses() {
1233 return uses;
1234 }
1235
1236 /**
1237 * <p> The services that this module provides. </p>
1238 *
1239 * @return The possibly-empty unmodifiable set of the services that this
1240 * module provides
1241 */
1242 public Set<Provides> provides() {
1243 return provides;
1244 }
1245
1246 /**
1247 * Returns this module's version.
1248 *
1249 * @return This module's version
1250 */
1251 public Optional<Version> version() {
1252 return Optional.ofNullable(version);
1253 }
1254
1255 /**
1256 * Returns a string containing this module's name and, if present, its
1257 * version.
1258 *
1259 * @return A string containing this module's name and, if present, its
1260 * version.
1261 */
1262 public String toNameAndVersion() {
1263 if (version != null) {
1264 return name() + "@" + version;
1265 } else {
1266 return name();
1267 }
1268 }
1269
1270 /**
1271 * Returns the module's main class.
1272 *
1273 * @return The fully qualified class name of this module's main class
1274 */
1275 public Optional<String> mainClass() {
1276 return Optional.ofNullable(mainClass);
1277 }
1278
1279 /**
1280 * Returns the operating system name if this module is operating system
1281 * specific.
1282 *
1283 * @return The operating system name or an empty {@code Optional}
1284 * if this module is not operating system specific
1285 */
1286 public Optional<String> osName() {
1287 return Optional.ofNullable(osName);
1288 }
1289
1290 /**
1291 * Returns the operating system architecture if this module is operating
1292 * system architecture specific.
1293 *
1294 * @return The operating system architecture or an empty {@code Optional}
1295 * if this module is not operating system architecture specific
1296 */
1297 public Optional<String> osArch() {
1298 return Optional.ofNullable(osArch);
1299 }
1300
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 }
1493
1494 /**
1495 * Adds an export.
1496 *
1497 * @param e
1498 * The export
1499 *
1500 * @return This builder
1501 *
1502 * @throws IllegalStateException
1503 * If the package is already declared as a package with the
1504 * {@link #contains contains} method or the package is already
1505 * declared as exported
1506 */
1507 public Builder exports(Exports e) {
1508 // can't be exported and concealed
1509 String source = e.source();
1510 if (concealedPackages.contains(source)) {
1511 throw new IllegalStateException("Package " + source
1512 + " already declared");
1513 }
1514 if (exports.containsKey(source)) {
1515 throw new IllegalStateException("Exported package " + source
1516 + " already declared");
1517 }
1518
1519 exports.put(source, e);
1520 return this;
1521 }
1522
1523 /**
1524 * Adds an export, with the given (and possibly empty) set of modifiers,
1525 * to export a package to a set of target modules.
1526 *
1527 * @param ms
1528 * The set of modifiers
1529 * @param pn
1530 * The package name
1531 * @param targets
1532 * The set of target modules names
1533 *
1534 * @return This builder
1535 *
1536 * @throws IllegalArgumentException
1537 * If the package name or any of the target modules is {@code
1538 * null} or is not a legal Java identifier, or the set of
1539 * targets is empty
1540 * @throws IllegalStateException
1541 * If the package is already declared as a package with the
1542 * {@link #contains contains} method or the package is already
1543 * declared as exported
1544 */
1545 public Builder exports(Set<Exports.Modifier> ms,
1546 String pn,
1547 Set<String> targets)
1548 {
1549 Exports e = new Exports(ms, requirePackageName(pn), targets);
1550
1551 // check targets
1552 targets = e.targets();
1553 if (targets.isEmpty())
1554 throw new IllegalArgumentException("Empty target set");
1555 if (strict)
1556 targets.stream().forEach(Checks::requireModuleName);
1557
1558 return exports(e);
1559 }
1560
1561 /**
1562 * Adds an unqualified export with the given (and possibly empty) set
1563 * of modifiers.
1564 *
1565 * @param ms
1566 * The set of modifiers
1567 * @param pn
1568 * The package name
1569 *
1570 * @return This builder
1571 *
1572 * @throws IllegalArgumentException
1573 * If the package name is {@code null} or is not a legal Java
1574 * identifier
1575 * @throws IllegalStateException
1576 * If the package is already declared as a package with the
1577 * {@link #contains contains} method or the package is already
1578 * declared as exported
1579 */
1580 public Builder exports(Set<Exports.Modifier> ms, String pn) {
1581 Exports e = new Exports(ms, requirePackageName(pn), Collections.emptySet());
1582 return exports(e);
1583 }
1584
1585 /**
1586 * Adds an export to export a package to a set of target modules.
1587 *
1588 * @param pn
1589 * The package name
1590 * @param targets
1591 * The set of target modules names
1592 *
1593 * @return This builder
1594 *
1595 * @throws IllegalArgumentException
1596 * If the package name or any of the target modules is {@code
1597 * null} or is not a legal Java identifier, or the set of
1598 * targets is empty
1599 * @throws IllegalStateException
1600 * If the package is already declared as a package with the
1601 * {@link #contains contains} method or the package is already
1602 * declared as exported
1603 */
1604 public Builder exports(String pn, Set<String> targets) {
1605 return exports(Collections.emptySet(), pn, targets);
1606 }
1607
1608 /**
1609 * Adds an unqualified export.
1610 *
1611 * @param pn
1612 * The package name
1613 *
1614 * @return This builder
1615 *
1616 * @throws IllegalArgumentException
1617 * If the package name is {@code null} or is not a legal Java
1618 * identifier
1619 * @throws IllegalStateException
1620 * If the package is already declared as a package with the
1621 * {@link #contains contains} method or the package is already
1622 * declared as exported
1623 */
1624 public Builder exports(String pn) {
1625 return exports(Collections.emptySet(), pn);
1626 }
1627
1628 /**
1629 * Adds an <em>opens</em> directive.
1630 *
1631 * @param obj
1632 * The {@code Opens} object
1633 *
1634 * @return This builder
1635 *
1636 * @throws IllegalStateException
1637 * If the package is already declared as a package with the
1638 * {@link #contains contains} method, the package is already
1639 * declared as open, or this is a builder for an open module
1640 */
1641 public Builder opens(Opens obj) {
1642 if (open) {
1643 throw new IllegalStateException("open modules cannot declare"
1644 + " open packages");
1645 }
1646
1647 // can't be open and concealed
1648 String source = obj.source();
1649 if (concealedPackages.contains(source)) {
1650 throw new IllegalStateException("Package " + source
1651 + " already declared");
1652 }
1653 if (opens.containsKey(source)) {
1654 throw new IllegalStateException("Open package " + source
1655 + " already declared");
1656 }
1657
1658 opens.put(source, obj);
1659 return this;
1660 }
1661
1662
1663 /**
1664 * Adds an <em>opens</em> directive, with the given (and possibly empty)
1665 * set of modifiers, to open a package to a set of target modules.
1666 *
1667 * @param ms
1668 * The set of modifiers
1669 * @param pn
1670 * The package name
1671 * @param targets
1672 * The set of target modules names
1673 *
1674 * @return This builder
1675 *
1676 * @throws IllegalArgumentException
1677 * If the package name or any of the target modules is {@code
1678 * null} or is not a legal Java identifier, or the set of
1679 * targets is empty
1680 * @throws IllegalStateException
1681 * If the package is already declared as a package with the
1682 * {@link #contains contains} method, the package is already
1683 * declared as open, or this is a builder for an open module
1684 */
1685 public Builder opens(Set<Opens.Modifier> ms,
1686 String pn,
1687 Set<String> targets)
1688 {
1689 Opens e = new Opens(ms, requirePackageName(pn), targets);
1690
1691 // check targets
1692 targets = e.targets();
1693 if (targets.isEmpty())
1694 throw new IllegalArgumentException("Empty target set");
1695 if (strict)
1696 targets.stream().forEach(Checks::requireModuleName);
1697
1698 return opens(e);
1699 }
1700
1701 /**
1702 * Adds an <em>opens</em> directive to open a package with the given (and
1703 * possibly empty) set of modifiers.
1704 *
1705 * @param ms
1706 * The set of modifiers
1707 * @param pn
1708 * The package name
1709 *
1710 * @return This builder
1711 *
1712 * @throws IllegalArgumentException
1713 * If the package name is {@code null} or is not a legal Java
1714 * identifier
1715 * @throws IllegalStateException
1716 * If the package is already declared as a package with the
1717 * {@link #contains contains} method, the package is already
1718 * declared as open, or this is a builder for an open module
1719 */
1720 public Builder opens(Set<Opens.Modifier> ms, String pn) {
1721 Opens e = new Opens(ms, requirePackageName(pn), Collections.emptySet());
1722 return opens(e);
1723 }
1724
1725 /**
1726 * Adds an <em>opens</em> directive to open a package to a set of target
1727 * modules.
1728 *
1729 * @param pn
1730 * The package name
1731 * @param targets
1732 * The set of target modules names
1733 *
1734 * @return This builder
1735 *
1736 * @throws IllegalArgumentException
1737 * If the package name or any of the target modules is {@code
1738 * null} or is not a legal Java identifier, or the set of
1739 * targets is empty
1740 * @throws IllegalStateException
1741 * If the package is already declared as a package with the
1742 * {@link #contains contains} method, the package is already
1743 * declared as open, or this is a builder for an open module
1744 */
1745 public Builder opens(String pn, Set<String> targets) {
1746 return opens(Collections.emptySet(), pn, targets);
1747 }
1748
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;
1789 }
1790
1791 /**
1792 * Provides a service with one or more implementations.
1793 *
1794 * @param p
1795 * The provides
1796 *
1797 * @return This builder
1798 *
1799 * @throws IllegalStateException
1800 * If the providers for the service type have already been
1801 * declared
1802 */
1803 public Builder provides(Provides p) {
1804 String st = p.service();
1805 if (provides.containsKey(st))
1806 throw new IllegalStateException("Providers of service "
1807 + st + " already declared");
1808 provides.put(st, p);
1809 return this;
1810 }
1811
1812 /**
1813 * Provides implementations of a service.
1814 *
1815 * @param service
1816 * The service type
1817 * @param providers
1818 * The list of provider or provider factory class names
1819 *
1820 * @return This builder
1821 *
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
1862 */
1863 public Builder provides(String service, String provider) {
1864 if (provider == null)
1865 throw new IllegalArgumentException("'provider' is null");
1866 return provides(service, List.of(provider));
1867 }
1868
1869 /**
1870 * Adds a (possible empty) set of packages to the module
1871 *
1872 * @param pns
1873 * The set of package names
1874 *
1875 * @return This builder
1876 *
1877 * @throws IllegalArgumentException
1878 * If any of the package names is {@code null} or is not a
1879 * legal Java identifier
1880 * @throws IllegalStateException
1881 * If any of packages are already declared as packages in
1882 * the module. This includes packages that are already
1883 * declared as exported or open packages.
1884 */
1885 public Builder contains(Set<String> pns) {
1886 pns.forEach(this::contains);
1887 return this;
1888 }
1889
1890 /**
1891 * Adds a package to the module.
1892 *
1893 * @param pn
1894 * The package name
1895 *
1896 * @return This builder
1897 *
1898 * @throws IllegalArgumentException
1899 * If the package name is {@code null}, or is not a legal Java
1900 * identifier
1901 * @throws IllegalStateException
1902 * If the package is already declared as a package in the
1903 * module. This includes the package already declared as an
1904 * exported or open package.
1905 */
1906 public Builder contains(String pn) {
1907 Checks.requirePackageName(pn);
1908 if (concealedPackages.contains(pn)) {
1909 throw new IllegalStateException("Package " + pn
1910 + " already declared");
1911 }
1912 if (exports.containsKey(pn)) {
1913 throw new IllegalStateException("Exported package "
1914 + pn + " already declared");
1915 }
1916 if (opens.containsKey(pn)) {
1917 throw new IllegalStateException("Open package "
1918 + pn + " already declared");
1919 }
1920 concealedPackages.add(pn);
1921 return this;
1922 }
1923
1924 /**
1925 * Sets the module version.
1926 *
1927 * @param v
1928 * The version
1929 *
1930 * @return This builder
1931 */
1932 public Builder version(Version v) {
1933 version = requireNonNull(v);
1934 return this;
1935 }
1936
1937 /**
1938 * Sets the module version.
1939 *
1940 * @param v
1941 * The version string to parse
1942 *
1943 * @return This builder
1944 *
1945 * @throws IllegalArgumentException
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 }
1987
1988 /**
1989 * Sets the operating system architecture.
1990 *
1991 * @param arch
1992 * The operating system architecture
1993 *
1994 * @return This builder
1995 *
1996 * @throws IllegalArgumentException
1997 * If {@code name} is null or the empty String
1998 */
1999 public Builder osArch(String arch) {
2000 if (arch == null || arch.isEmpty())
2001 throw new IllegalArgumentException("OS arch is null or empty");
2002 osArch = arch;
2003 return this;
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
2077 * descriptor is less than, equal to, or greater than the given
2078 * module descriptor
2079 */
2080 @Override
2081 public int compareTo(ModuleDescriptor that) {
2082 int c = this.name().compareTo(that.name());
2083 if (c != 0) return c;
2084 if (version == null) {
2085 if (that.version == null)
2086 return 0;
2087 return -1;
2088 }
2089 if (that.version == null)
2090 return +1;
2091 return version.compareTo(that.version);
2092 }
2093
2094 /**
2095 * Tests this module descriptor for equality with the given object.
2096 *
2097 * <p> If the given object is not a {@code ModuleDescriptor} then this
2098 * method returns {@code false}. Two module descriptors are equal if each
2099 * of their corresponding components is equal. </p>
2100 *
2101 * <p> This method satisfies the general contract of the {@link
2102 * java.lang.Object#equals(Object) Object.equals} method. </p>
2103 *
2104 * @param ob
2105 * the object to which this object is to be compared
2106 *
2107 * @return {@code true} if, and only if, the given object is a module
2108 * descriptor that is equal to this module descriptor
2109 */
2110 @Override
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 *
2283 * @apiNote The {@code packageFinder} parameter is for use when reading
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 }
2458
2459 @Override
2460 public Opens newOpens(Set<Opens.Modifier> ms, String source) {
2461 return new Opens(ms, source, Collections.emptySet(), true);
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 }
|
1 /*
2 * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
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.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Objects;
44 import java.util.Optional;
45 import java.util.Set;
46 import java.util.TreeSet;
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.ModuleInfo;
56
57
58 /**
59 * A module descriptor.
60 *
61 * <p> A module descriptor describes a named module and defines methods to
62 * obtain each of its components. The module descriptor for a named module
63 * in the Java virtual machine is obtained by invoking the {@link
64 * java.lang.reflect.Module Module}'s {@link java.lang.reflect.Module#getDescriptor
65 * getDescriptor} method. Module descriptors can also be created using the
66 * {@link ModuleDescriptor.Builder} class or by reading the binary form of a
67 * module declaration ({@code module-info.class}) using the {@link
68 * #read(InputStream,Supplier) read} methods defined here. </p>
69 *
70 * <p> A module descriptor describes a <em>normal</em>, open, or automatic
71 * module. <em>Normal</em> modules and open modules describe their {@link
72 * #requires() dependences}, {@link #exports() exported-packages}, the services
73 * that they {@link #uses() use} or {@link #provides() provide}, and other
74 * components. <em>Normal</em> modules may {@link #opens() open} specific
75 * packages. The module descriptor for an open modules does not declare any
76 * open packages (its {@code opens} method returns an empty set) but when
77 * instantiated in the Java virtual machine then it is treated as if all
78 * packages are open. The module descriptor for an automatic module does not
79 * declare any dependences (except for the mandatory dependency on {@code
80 * java.base}), and does not declare any exported or open packages. Automatic
81 * module receive special treatment during resolution so that they read all
82 * other modules in the configuration. When an automatic module is instantiated
83 * in the Java virtual machine then it reads every unnamed module and is
84 * treated as if all packages are exported and open. </p>
85 *
86 * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
87 * multiple concurrent threads.</p>
88 *
89 * @see java.lang.reflect.Module
90 * @since 9
91 * @spec JPMS
92 */
93
94 public class ModuleDescriptor
95 implements Comparable<ModuleDescriptor>
96 {
97
98 /**
99 * A modifier on a module.
100 *
101 * @see ModuleDescriptor#modifiers()
102 * @since 9
103 */
104 public static enum Modifier {
105 /**
106 * An open module. An open module does not declare any open packages
107 * but the resulting module is treated as if all packages are open.
108 */
109 OPEN,
110
111 /**
112 * An automatic module. An automatic module is treated as if it exports
113 * and opens all packages.
114 *
115 * @apiNote This modifier does not correspond to a module flag in the
116 * binary form of a module declaration ({@code module-info.class}).
117 */
118 AUTOMATIC,
119
120 /**
121 * The module was not explicitly or implicitly declared.
122 */
123 SYNTHETIC,
124
125 /**
126 * The module was implicitly declared.
127 */
128 MANDATED;
129 }
130
131
132 /**
133 * <p> A dependence upon a module </p>
134 *
135 * @see ModuleDescriptor#requires()
136 * @since 9
137 * @spec JPMS
138 */
139
140 public final static class Requires
141 implements Comparable<Requires>
142 {
143
144 /**
145 * A modifier on a module dependence.
146 *
147 * @see Requires#modifiers()
148 * @since 9
149 * @spec JPMS
150 */
151 public static enum Modifier {
152
153 /**
154 * The dependence causes any module which depends on the <i>current
155 * module</i> to have an implicitly declared dependence on the module
156 * named by the {@code Requires}.
157 */
158 TRANSITIVE,
159
160 /**
161 * The dependence is mandatory in the static phase, during compilation,
162 * but is optional in the dynamic phase, during execution.
163 */
164 STATIC,
165
166 /**
167 * The dependence was not explicitly or implicitly declared in the
168 * source of the module declaration.
169 */
212 *
213 * @return The module name
214 */
215 public String name() {
216 return name;
217 }
218
219 /**
220 * Returns the version of the module if recorded at compile-time.
221 *
222 * @return The version of the module if recorded at compile-time
223 */
224 public Optional<Version> compiledVersion() {
225 return Optional.ofNullable(compiledVersion);
226 }
227
228 /**
229 * Compares this module dependence to another.
230 *
231 * <p> Two {@code Requires} objects are compared by comparing their
232 * module names lexicographically. Where the module names are equal
233 * then the sets of modifiers are compared in the same way that
234 * module modifiers are compared (see {@link ModuleDescriptor#compareTo
235 * ModuleDescriptor.compareTo}). Where the module names are equal and
236 * the set of modifiers are equal then the version of the modules
237 * recorded at compile-time are compared. When comparing the versions
238 * recorded at compile-time then a dependence that has a recorded
239 * version is considered to succeed a dependence that does not have a
240 * recorded version. </p>
241 *
242 * @param that
243 * The module dependence to compare
244 *
245 * @return A negative integer, zero, or a positive integer if this module
246 * dependence is less than, equal to, or greater than the given
247 * module dependence
248 */
249 @Override
250 public int compareTo(Requires that) {
251 if (this == that) return 0;
252
253 int c = this.name().compareTo(that.name());
254 if (c != 0) return c;
255
256 // modifiers
257 long v1 = modsValue(this.modifiers());
258 long v2 = modsValue(that.modifiers());
259 c = Long.compare(v1, v2);
260 if (c != 0) return c;
261
262 // compiledVersion
263 c = compare(this.compiledVersion, that.compiledVersion);
264 if (c != 0) return c;
265
266 return 0;
267 }
268
269 /**
270 * Tests this module dependence for equality with the given object.
271 *
272 * <p> If the given object is not a {@code Requires} then this method
273 * returns {@code false}. Two module dependence objects are equal if
274 * the module names are equal, set of modifiers are equal, and the
275 * compiled version of both modules is equal or not recorded for
276 * both modules. </p>
277 *
278 * <p> This method satisfies the general contract of the {@link
279 * java.lang.Object#equals(Object) Object.equals} method. </p>
280 *
281 * @param ob
282 * the object to which this object is to be compared
283 *
284 * @return {@code true} if, and only if, the given object is a module
285 * dependence that is equal to this module dependence
286 */
294 }
295
296 /**
297 * Computes a hash code for this module dependence.
298 *
299 * <p> The hash code is based upon the module name, modifiers, and the
300 * module version if recorded at compile time. It satisfies the general
301 * contract of the {@link Object#hashCode Object.hashCode} method. </p>
302 *
303 * @return The hash-code value for this module dependence
304 */
305 @Override
306 public int hashCode() {
307 int hash = name.hashCode() * 43 + mods.hashCode();
308 if (compiledVersion != null)
309 hash = hash * 43 + compiledVersion.hashCode();
310 return hash;
311 }
312
313 /**
314 * Returns a string describing this module dependence.
315 *
316 * @return A string describing this module dependence
317 */
318 @Override
319 public String toString() {
320 String what;
321 if (compiledVersion != null) {
322 what = name() + " (@" + compiledVersion + ")";
323 } else {
324 what = name();
325 }
326 return ModuleDescriptor.toString(mods, what);
327 }
328 }
329
330
331
332 /**
333 * <p> A package exported by a module, may be qualified or unqualified. </p>
334 *
335 * @see ModuleDescriptor#exports()
336 * @since 9
337 * @spec JPMS
338 */
339
340 public final static class Exports
341 implements Comparable<Exports>
342 {
343
344 /**
345 * A modifier on an exported package.
346 *
347 * @see Exports#modifiers()
348 * @since 9
349 * @spec JPMS
350 */
351 public static enum Modifier {
352
353 /**
354 * The export was not explicitly or implicitly declared in the
355 * source of the module declaration.
356 */
357 SYNTHETIC,
358
359 /**
360 * The export was implicitly declared in the source of the module
361 * declaration.
362 */
363 MANDATED;
364
365 }
366
367 private final Set<Modifier> mods;
368 private final String source;
369 private final Set<String> targets; // empty if unqualified export
414 *
415 * @return The package name
416 */
417 public String source() {
418 return source;
419 }
420
421 /**
422 * For a qualified export, returns the non-empty and immutable set
423 * of the module names to which the package is exported. For an
424 * unqualified export, returns an empty set.
425 *
426 * @return The set of target module names or for an unqualified
427 * export, an empty set
428 */
429 public Set<String> targets() {
430 return targets;
431 }
432
433 /**
434 * Compares this module export to another.
435 *
436 * <p> Two {@code Exports} objects are compared by comparing the package
437 * names lexicographically. Where the packages names are equal then the
438 * sets of modifiers are compared in the same way that module modifiers
439 * are compared (see {@link ModuleDescriptor#compareTo
440 * ModuleDescriptor.compareTo}). Where the package names are equal and
441 * the set of modifiers are equal then the set of target modules are
442 * compared. This is done by sorting the sets, iterating over both sets
443 * in ascending order, and comparing the corresponding elements
444 * lexicographically. Where the sets differ in size, and the larger set
445 * contains all elements of the smaller set, then the larger set is
446 * considered to succeed the smaller set. </p>
447 *
448 * @param that
449 * The module export to compare
450 *
451 * @return A negative integer, zero, or a positive integer if this module
452 * export is less than, equal to, or greater than the given
453 * export dependence
454 */
455 @Override
456 public int compareTo(Exports that) {
457 if (this == that) return 0;
458
459 int c = source.compareTo(that.source);
460 if (c != 0)
461 return c;
462
463 // modifiers
464 long v1 = modsValue(this.modifiers());
465 long v2 = modsValue(that.modifiers());
466 c = Long.compare(v1, v2);
467 if (c != 0)
468 return c;
469
470 // targets
471 c = compare(targets, that.targets);
472 if (c != 0)
473 return c;
474
475 return 0;
476 }
477
478 /**
479 * Computes a hash code for this module export.
480 *
481 * <p> The hash code is based upon the modifiers, the package name,
482 * and for a qualified export, the set of modules names to which the
483 * package is exported. It satisfies the general contract of the
484 * {@link Object#hashCode Object.hashCode} method.
485 *
486 * @return The hash-code value for this module export
487 */
488 @Override
489 public int hashCode() {
490 int hash = mods.hashCode();
491 hash = hash * 43 + source.hashCode();
492 return hash * 43 + targets.hashCode();
493 }
494
495 /**
496 * Tests this module export for equality with the given object.
497 *
498 * <p> If the given object is not an {@code Exports} then this method
503 * <p> This method satisfies the general contract of the {@link
504 * java.lang.Object#equals(Object) Object.equals} method. </p>
505 *
506 * @param ob
507 * the object to which this object is to be compared
508 *
509 * @return {@code true} if, and only if, the given object is a module
510 * dependence that is equal to this module dependence
511 */
512 @Override
513 public boolean equals(Object ob) {
514 if (!(ob instanceof Exports))
515 return false;
516 Exports other = (Exports)ob;
517 return Objects.equals(this.mods, other.mods)
518 && Objects.equals(this.source, other.source)
519 && Objects.equals(this.targets, other.targets);
520 }
521
522 /**
523 * Returns a string describing the exported package.
524 *
525 * @return A string describing the exported package
526 */
527 @Override
528 public String toString() {
529 String s = ModuleDescriptor.toString(mods, source);
530 if (targets.isEmpty())
531 return s;
532 else
533 return s + " to " + targets;
534 }
535 }
536
537
538 /**
539 * <p> A package opened by a module, may be qualified or unqualified. </p>
540 *
541 * <p> The <em>opens</em> directive in a module declaration declares a
542 * package to be open to allow all types in the package, and all their
543 * members, not just public types and their public members to be reflected
544 * on by APIs that support private access or a way to bypass or suppress
545 * default Java language access control checks. </p>
546 *
547 * @see ModuleDescriptor#opens()
548 * @since 9
549 * @spec JPMS
550 */
551
552 public final static class Opens
553 implements Comparable<Opens>
554 {
555 /**
556 * A modifier on an open package.
557 *
558 * @see Opens#modifiers()
559 * @since 9
560 * @spec JPMS
561 */
562 public static enum Modifier {
563
564 /**
565 * The open package was not explicitly or implicitly declared in
566 * the source of the module declaration.
567 */
568 SYNTHETIC,
569
570 /**
571 * The open package was implicitly declared in the source of the
572 * module declaration.
573 */
574 MANDATED;
575
576 }
577
578 private final Set<Modifier> mods;
579 private final String source;
580 private final Set<String> targets; // empty if unqualified export
581
582 /**
583 * Constructs an Opens
584 */
585 private Opens(Set<Modifier> ms, String source, Set<String> targets) {
586 if (ms.isEmpty()) {
587 ms = Collections.emptySet();
588 } else {
589 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
590 }
591 this.mods = ms;
592 this.source = source;
625 *
626 * @return The package name
627 */
628 public String source() {
629 return source;
630 }
631
632 /**
633 * For a qualified opens, returns the non-empty and immutable set
634 * of the module names to which the package is open. For an
635 * unqualified opens, returns an empty set.
636 *
637 * @return The set of target module names or for an unqualified
638 * opens, an empty set
639 */
640 public Set<String> targets() {
641 return targets;
642 }
643
644 /**
645 * Compares this module opens to another.
646 *
647 * <p> Two {@code Opens} objects are compared by comparing the package
648 * names lexicographically. Where the packages names are equal then the
649 * sets of modifiers are compared in the same way that module modifiers
650 * are compared (see {@link ModuleDescriptor#compareTo
651 * ModuleDescriptor.compareTo}). Where the package names are equal and
652 * the set of modifiers are equal then the set of target modules are
653 * compared. This is done by sorting the sets, iterating over both sets
654 * in ascending order, and comparing the corresponding elements
655 * lexicographically. Where the sets differ in size, and the larger set
656 * contains all elements of the smaller set, then the larger set is
657 * considered to succeed the smaller set. </p>
658 *
659 * @param that
660 * The module opens to compare
661 *
662 * @return A negative integer, zero, or a positive integer if this module
663 * opens is less than, equal to, or greater than the given
664 * module opens
665 */
666 @Override
667 public int compareTo(Opens that) {
668 if (this == that) return 0;
669
670 int c = source.compareTo(that.source);
671 if (c != 0)
672 return c;
673
674 // modifiers
675 long v1 = modsValue(this.modifiers());
676 long v2 = modsValue(that.modifiers());
677 c = Long.compare(v1, v2);
678 if (c != 0)
679 return c;
680
681 // targets
682 c = compare(targets, that.targets);
683 if (c != 0)
684 return c;
685
686 return 0;
687 }
688
689 /**
690 * Computes a hash code for this module opens.
691 *
692 * <p> The hash code is based upon the modifiers, the package name,
693 * and for a qualified opens, the set of modules names to which the
694 * package is opened. It satisfies the general contract of the
695 * {@link Object#hashCode Object.hashCode} method.
696 *
697 * @return The hash-code value for this module opens
698 */
699 @Override
700 public int hashCode() {
701 int hash = mods.hashCode();
702 hash = hash * 43 + source.hashCode();
703 return hash * 43 + targets.hashCode();
704 }
705
706 /**
707 * Tests this module opens for equality with the given object.
708 *
709 * <p> If the given object is not an {@code Opens} then this method
714 * <p> This method satisfies the general contract of the {@link
715 * java.lang.Object#equals(Object) Object.equals} method. </p>
716 *
717 * @param ob
718 * the object to which this object is to be compared
719 *
720 * @return {@code true} if, and only if, the given object is a module
721 * dependence that is equal to this module dependence
722 */
723 @Override
724 public boolean equals(Object ob) {
725 if (!(ob instanceof Opens))
726 return false;
727 Opens other = (Opens)ob;
728 return Objects.equals(this.mods, other.mods)
729 && Objects.equals(this.source, other.source)
730 && Objects.equals(this.targets, other.targets);
731 }
732
733 /**
734 * Returns a string describing the open package.
735 *
736 * @return A string describing the open package
737 */
738 @Override
739 public String toString() {
740 String s = ModuleDescriptor.toString(mods, source);
741 if (targets.isEmpty())
742 return s;
743 else
744 return s + " to " + targets;
745 }
746 }
747
748
749 /**
750 * <p> A service that a module provides one or more implementations of. </p>
751 *
752 * @see ModuleDescriptor#provides()
753 * @since 9
754 * @spec JPMS
755 */
756
757 public final static class Provides
758 implements Comparable<Provides>
759 {
760 private final String service;
761 private final List<String> providers;
762
763 private Provides(String service, List<String> providers) {
764 this.service = service;
765 this.providers = Collections.unmodifiableList(providers);
766 }
767
768 private Provides(String service, List<String> providers, boolean unused) {
769 this.service = service;
770 this.providers = providers;
771 }
772
773 /**
774 * Returns the fully qualified class name of the service type.
775 *
776 * @return The fully qualified class name of the service type.
777 */
778 public String service() { return service; }
779
780 /**
781 * Returns the list of the fully qualified class names of the providers
782 * or provider factories.
783 *
784 * @return A non-empty and unmodifiable list of the fully qualified class
785 * names of the providers or provider factories
786 */
787 public List<String> providers() { return providers; }
788
789 /**
790 * Compares this provides to another.
791 *
792 * <p> Two {@code Provides} objects are compared by comparing the fully
793 * qualified class name of the service type lexicographically. Where the
794 * class names are equal then the list of the provider class names are
795 * compared by comparing the corresponding elements of both lists
796 * lexicographically and in sequence. Where the lists differ in size,
797 * {@code N} is the size of the shorter list, and the first {@code N}
798 * corresponding elements are equal, then the longer list is considered
799 * to succeed the shorter list. </p>
800 *
801 * @param that
802 * The {@code Provides} to compare
803 *
804 * @return A negative integer, zero, or a positive integer if this provides
805 * is less than, equal to, or greater than the given provides
806 */
807 public int compareTo(Provides that) {
808 if (this == that) return 0;
809
810 int c = service.compareTo(that.service);
811 if (c != 0) return c;
812
813 // compare provider class names in sequence
814 int size1 = this.providers.size();
815 int size2 = that.providers.size();
816 for (int index=0; index<Math.min(size1, size2); index++) {
817 String e1 = this.providers.get(index);
818 String e2 = that.providers.get(index);
819 c = e1.compareTo(e2);
820 if (c != 0) return c;
821 }
822 if (size1 == size2) {
823 return 0;
824 } else {
825 return (size1 > size2) ? 1 : -1;
826 }
827 }
828
829 /**
830 * Computes a hash code for this provides.
831 *
832 * <p> The hash code is based upon the service type and the set of
833 * providers. It satisfies the general contract of the {@link
834 * Object#hashCode Object.hashCode} method. </p>
835 *
836 * @return The hash-code value for this module provides
837 */
838 @Override
839 public int hashCode() {
840 return service.hashCode() * 43 + providers.hashCode();
841 }
842
843 /**
844 * Tests this provides for equality with the given object.
845 *
846 * <p> If the given object is not a {@code Provides} then this method
847 * returns {@code false}. Two {@code Provides} objects are equal if the
848 * service type is equal and the list of providers is equal. </p>
849 *
867
868 /**
869 * Returns a string describing this provides.
870 *
871 * @return A string describing this provides
872 */
873 @Override
874 public String toString() {
875 return service + " with " + providers;
876 }
877
878 }
879
880
881
882 /**
883 * A module's version string.
884 *
885 * <p> A version string has three components: The version number itself, an
886 * optional pre-release version, and an optional build version. Each
887 * component is a sequence of tokens; each token is either a non-negative
888 * integer or a string. Tokens are separated by the punctuation characters
889 * {@code '.'}, {@code '-'}, or {@code '+'}, or by transitions from a
890 * sequence of digits to a sequence of characters that are neither digits
891 * nor punctuation characters, or vice versa.
892 *
893 * <ul>
894 *
895 * <li> The <i>version number</i> is a sequence of tokens separated by
896 * {@code '.'} characters, terminated by the first {@code '-'} or {@code
897 * '+'} character. </li>
898 *
899 * <li> The <i>pre-release version</i> is a sequence of tokens separated
900 * by {@code '.'} or {@code '-'} characters, terminated by the first
901 * {@code '+'} character. </li>
902 *
903 * <li> The <i>build version</i> is a sequence of tokens separated by
904 * {@code '.'}, {@code '-'}, or {@code '+'} characters.
905 *
906 * </ul>
907 *
908 * <p> When comparing two version strings, the elements of their
909 * corresponding components are compared in pointwise fashion. If one
910 * component is longer than the other, but otherwise equal to it, then the
911 * first component is considered the greater of the two; otherwise, if two
912 * corresponding elements are integers then they are compared as such;
913 * otherwise, at least one of the elements is a string, so the other is
914 * converted into a string if it is an integer and the two are compared
915 * lexicographically. Trailing integer elements with the value zero are
916 * ignored.
917 *
918 * <p> Given two version strings, if their version numbers differ then the
919 * result of comparing them is the result of comparing their version
920 * numbers; otherwise, if one of them has a pre-release version but the
921 * other does not then the first is considered to precede the second,
922 * otherwise the result of comparing them is the result of comparing their
923 * pre-release versions; otherwise, the result of comparing them is the
924 * result of comparing their build versions.
925 *
926 * @see ModuleDescriptor#version()
927 * @since 9
928 * @spec JPMS
929 */
930
931 public final static class Version
932 implements Comparable<Version>
933 {
934
935 private final String version;
936
937 // If Java had disjunctive types then we'd write List<Integer|String> here
938 //
939 private final List<Object> sequence;
940 private final List<Object> pre;
941 private final List<Object> build;
942
943 // Take a numeric token starting at position i
944 // Append it to the given list
945 // Return the index of the first character not taken
946 // Requires: s.charAt(i) is (decimal) numeric
947 //
948 private static int takeNumber(String s, int i, List<Object> acc) {
1181 @Override
1182 public int hashCode() {
1183 return version.hashCode();
1184 }
1185
1186 /**
1187 * Returns the string from which this version was parsed.
1188 *
1189 * @return The string from which this version was parsed.
1190 */
1191 @Override
1192 public String toString() {
1193 return version;
1194 }
1195
1196 }
1197
1198
1199 private final String name;
1200 private final Version version;
1201 private final Set<Modifier> modifiers;
1202 private final boolean open; // true if modifiers contains OPEN
1203 private final boolean automatic; // true if modifiers contains AUTOMATIC
1204 private final Set<Requires> requires;
1205 private final Set<Exports> exports;
1206 private final Set<Opens> opens;
1207 private final Set<String> uses;
1208 private final Set<Provides> provides;
1209 private final Set<String> packages;
1210 private final String mainClass;
1211 private final String osName;
1212 private final String osArch;
1213 private final String osVersion;
1214
1215 private ModuleDescriptor(String name,
1216 Version version,
1217 Set<Modifier> modifiers,
1218 Set<Requires> requires,
1219 Set<Exports> exports,
1220 Set<Opens> opens,
1221 Set<String> uses,
1222 Set<Provides> provides,
1223 Set<String> packages,
1224 String mainClass,
1225 String osName,
1226 String osArch,
1227 String osVersion)
1228 {
1229 this.name = name;
1230 this.version = version;
1231 this.modifiers = emptyOrUnmodifiableSet(modifiers);
1232 this.open = modifiers.contains(Modifier.OPEN);
1233 this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1234 assert (requires.stream().map(Requires::name).distinct().count()
1235 == requires.size());
1236 this.requires = emptyOrUnmodifiableSet(requires);
1237 this.exports = emptyOrUnmodifiableSet(exports);
1238 this.opens = emptyOrUnmodifiableSet(opens);
1239 this.uses = emptyOrUnmodifiableSet(uses);
1240 this.provides = emptyOrUnmodifiableSet(provides);
1241
1242 this.packages = emptyOrUnmodifiableSet(packages);
1243 this.mainClass = mainClass;
1244 this.osName = osName;
1245 this.osArch = osArch;
1246 this.osVersion = osVersion;
1247 }
1248
1249 /**
1250 * Creates a module descriptor from its components.
1251 * The arguments are pre-validated and sets are unmodifiable sets.
1252 */
1253 ModuleDescriptor(String name,
1254 Version version,
1255 Set<Modifier> modifiers,
1256 Set<Requires> requires,
1257 Set<Exports> exports,
1258 Set<Opens> opens,
1259 Set<String> uses,
1260 Set<Provides> provides,
1261 Set<String> packages,
1262 String mainClass,
1263 String osName,
1264 String osArch,
1265 String osVersion,
1266 int hashCode,
1267 boolean unused) {
1268 this.name = name;
1269 this.version = version;
1270 this.modifiers = modifiers;
1271 this.open = modifiers.contains(Modifier.OPEN);
1272 this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1273 this.requires = requires;
1274 this.exports = exports;
1275 this.opens = opens;
1276 this.uses = uses;
1277 this.provides = provides;
1278 this.packages = packages;
1279 this.mainClass = mainClass;
1280 this.osName = osName;
1281 this.osArch = osArch;
1282 this.osVersion = osVersion;
1283 this.hash = hashCode;
1284 }
1285
1286 /**
1287 * <p> Returns the module name. </p>
1288 *
1289 * @return The module name
1290 */
1291 public String name() {
1292 return name;
1293 }
1294
1295 /**
1296 * <p> Returns the set of module modifiers. </p>
1297 *
1298 * @return A possibly-empty unmodifiable set of modifiers
1299 */
1300 public Set<Modifier> modifiers() {
1301 return modifiers;
1302 }
1303
1304 /**
1305 * <p> Returns {@code true} if this is an open module. </p>
1306 *
1307 * <p> This method is equivalent to testing if the set of {@link #modifiers
1308 * modifiers} contains the {@link Modifier#OPEN OPEN} modifier. </p>
1309 *
1310 * @return {@code true} if this is an open module
1311 */
1312 public boolean isOpen() {
1313 return open;
1314 }
1315
1316 /**
1317 * <p> Returns {@code true} if this is an automatic module. </p>
1318 *
1319 * <p> This method is equivalent to testing if the set of {@link #modifiers
1320 * modifiers} contains the {@link Modifier#OPEN AUTOMATIC} modifier. </p>
1321 *
1322 * @return {@code true} if this is an automatic module
1323 */
1324 public boolean isAutomatic() {
1325 return automatic;
1326 }
1327
1328 /**
1329 * <p> Returns the set of module dependences. </p>
1330 *
1331 * <p> The set includes a dependency on "{@code java.base}" when this
1332 * module is not named "{@code java.base}". If this module is an automatic
1333 * module then it does not have a dependency on any module other than
1334 * "{@code java.base}". </p>
1335 *
1336 * @return A possibly-empty unmodifiable set of {@link Requires} objects
1337 */
1338 public Set<Requires> requires() {
1339 return requires;
1340 }
1341
1342 /**
1343 * <p> Returns the set of exported packages. </p>
1344 *
1345 * <p> If this module is an automatic module then the set of exports
1346 * is empty. </p>
1347 *
1348 * @return A possibly-empty unmodifiable set of exported packages
1349 */
1350 public Set<Exports> exports() {
1351 return exports;
1352 }
1353
1354 /**
1355 * <p> Returns the set of open packages. </p>
1356 *
1357 * <p> If this module is an open module or an automatic module then the
1358 * set of open packages is empty. </p>
1359 *
1360 * @return A possibly-empty unmodifiable set of open packages
1361 */
1362 public Set<Opens> opens() {
1363 return opens;
1364 }
1365
1366 /**
1367 * <p> Returns the set of service dependences. </p>
1368 *
1369 * <p> If this module is an automatic module then the set of service
1370 * dependences is empty. </p>
1371 *
1372 * @return A possibly-empty unmodifiable set of the fully qualified class
1373 * names of the service types used
1374 */
1375 public Set<String> uses() {
1376 return uses;
1377 }
1378
1379 /**
1380 * <p> Returns the set of services that the module provides. </p>
1381 *
1382 * @return The possibly-empty unmodifiable set of the services that this
1383 * module provides
1384 */
1385 public Set<Provides> provides() {
1386 return provides;
1387 }
1388
1389 /**
1390 * <p> Returns the module version. </p>
1391 *
1392 * @return This module's version
1393 */
1394 public Optional<Version> version() {
1395 return Optional.ofNullable(version);
1396 }
1397
1398 /**
1399 * <p> Returns a string containing the module name and, if present, its
1400 * version. </p>
1401 *
1402 * @return A string containing the module name and, if present, its
1403 * version.
1404 */
1405 public String toNameAndVersion() {
1406 if (version != null) {
1407 return name() + "@" + version;
1408 } else {
1409 return name();
1410 }
1411 }
1412
1413 /**
1414 * <p> Returns the module main class. </p>
1415 *
1416 * @return The fully qualified class name of the module's main class
1417 */
1418 public Optional<String> mainClass() {
1419 return Optional.ofNullable(mainClass);
1420 }
1421
1422 /**
1423 * Returns the operating system name if the module is operating system
1424 * specific.
1425 *
1426 * @return The operating system name or an empty {@code Optional}
1427 * if the module is not operating system specific
1428 */
1429 public Optional<String> osName() {
1430 return Optional.ofNullable(osName);
1431 }
1432
1433 /**
1434 * Returns the operating system architecture if the module is operating
1435 * system architecture specific.
1436 *
1437 * @return The operating system architecture or an empty {@code Optional}
1438 * if the module is not operating system architecture specific
1439 */
1440 public Optional<String> osArch() {
1441 return Optional.ofNullable(osArch);
1442 }
1443
1444 /**
1445 * Returns the operating system version if the module is operating
1446 * system version specific.
1447 *
1448 * @return The operating system version or an empty {@code Optional}
1449 * if the module is not operating system version specific
1450 */
1451 public Optional<String> osVersion() {
1452 return Optional.ofNullable(osVersion);
1453 }
1454
1455 /**
1456 * Returns the set of packages in the module.
1457 *
1458 * @return A possibly-empty unmodifiable set of the packages in the module
1459 */
1460 public Set<String> packages() {
1461 return packages;
1462 }
1463
1464
1465 /**
1466 * A builder for building {@link ModuleDescriptor} objects.
1467 *
1468 * <p> {@code ModuleDescriptor} defines the {@link #newModule newModule},
1469 * {@link #newOpenModule newOpenModule}, and {@link #newAutomaticModule
1470 * newAutomaticModule} methods to create builders for building
1471 * <em>normal</em>, open, and automatic modules. </p>
1472 *
1473 * <p> The set of packages in the module are accumulated by the {@code
1474 * Builder} as the {@link ModuleDescriptor.Builder#exports(String) exports},
1475 * {@link ModuleDescriptor.Builder#opens(String) opens},
1476 * {@link ModuleDescriptor.Builder#packages(Set) packages},
1477 * {@link ModuleDescriptor.Builder#provides(String,List) provides}, and
1478 * {@link ModuleDescriptor.Builder#mainClass(String) mainClass} methods are
1479 * invoked. </p>
1480 *
1481 * <p> The module names, package names, and class names that are parameters
1482 * specified to the builder methods are the module names, package names,
1483 * and qualified names of classes (in named packages) as defined in the
1484 * <cite>The Java™ Language Specification</cite>. </p>
1485 *
1486 * <p> Example usage: </p>
1487 * <pre>{@code ModuleDescriptor descriptor = ModuleDescriptor.newModule("stats.core")
1488 * .requires("java.base")
1489 * .exports("org.acme.stats.core.clustering")
1490 * .exports("org.acme.stats.core.regression")
1491 * .packages(Set.of("org.acme.stats.core.internal"))
1492 * .build();
1493 * }</pre>
1494 *
1495 * @apiNote A {@code Builder} checks the components and invariants as
1496 * components are added to the builder. The rationale for this is to detect
1497 * errors as early as possible and not defer all validation to the
1498 * {@link #build build} method.
1499 *
1500 * @since 9
1501 * @spec JPMS
1502 */
1503 public static final class Builder {
1504 final String name;
1505 final boolean strict;
1506 final Set<Modifier> modifiers;
1507 final boolean open;
1508 final boolean automatic;
1509 final Set<String> packages = new HashSet<>();
1510 final Map<String, Requires> requires = new HashMap<>();
1511 final Map<String, Exports> exports = new HashMap<>();
1512 final Map<String, Opens> opens = new HashMap<>();
1513 final Set<String> uses = new HashSet<>();
1514 final Map<String, Provides> provides = new HashMap<>();
1515 Version version;
1516 String osName;
1517 String osArch;
1518 String osVersion;
1519 String mainClass;
1520
1521 /**
1522 * Initializes a new builder with the given module name.
1523 *
1524 * If {@code strict} is {@code true} then module, package, and class
1525 * names are checked to ensure they are legal names. In addition, the
1526 * {@link #build buid} method will add "{@code requires java.base}" if
1527 * the dependency is not declared.
1528 */
1529 Builder(String name, boolean strict, Set<Modifier> modifiers) {
1530 this.name = (strict) ? requireModuleName(name) : name;
1531 this.strict = strict;
1532 this.modifiers = modifiers;
1533 this.open = modifiers.contains(Modifier.OPEN);
1534 this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1535 assert !open || !automatic;
1536 }
1537
1538 /**
1539 * Returns a snapshot of the packages in the module.
1540 */
1541 /* package */ Set<String> packages() {
1542 return Collections.unmodifiableSet(packages);
1543 }
1544
1545 /**
1546 * Adds a dependence on a module.
1547 *
1548 * @param req
1549 * The dependence
1550 *
1551 * @return This builder
1552 *
1553 * @throws IllegalArgumentException
1554 * If the dependence is on the module that this builder was
1555 * initialized to build
1556 * @throws IllegalStateException
1557 * If the dependence on the module has already been declared
1558 * or this builder is for an automatic module
1559 */
1560 public Builder requires(Requires req) {
1561 if (automatic)
1562 throw new IllegalStateException("Automatic modules cannot declare"
1563 + " dependences");
1564 String mn = req.name();
1565 if (name.equals(mn))
1566 throw new IllegalArgumentException("Dependence on self");
1567 if (requires.containsKey(mn))
1568 throw new IllegalStateException("Dependence upon " + mn
1569 + " already declared");
1570 requires.put(mn, req);
1571 return this;
1572 }
1573
1574 /**
1575 * Adds a dependence on a module with the given (and possibly empty)
1576 * set of modifiers. The dependence includes the version of the
1577 * module that that was recorded at compile-time.
1578 *
1579 * @param ms
1580 * The set of modifiers
1581 * @param mn
1582 * The module name
1583 * @param compiledVersion
1584 * The version of the module recorded at compile-time
1585 *
1586 * @return This builder
1587 *
1588 * @throws IllegalArgumentException
1589 * If the module name is {@code null}, is not a legal module
1590 * name, or is equal to the module name that this builder
1591 * was initialized to build
1592 * @throws IllegalStateException
1593 * If the dependence on the module has already been declared
1594 * or this builder is for an automatic module
1595 */
1596 public Builder requires(Set<Requires.Modifier> ms,
1597 String mn,
1598 Version compiledVersion) {
1599 Objects.requireNonNull(compiledVersion);
1600 if (strict)
1601 mn = requireModuleName(mn);
1602 return requires(new Requires(ms, mn, compiledVersion));
1603 }
1604
1605 /* package */Builder requires(Set<Requires.Modifier> ms,
1606 String mn,
1607 String compiledVersion) {
1608 Version v = null;
1609 try {
1610 v = Version.parse(compiledVersion);
1611 } catch (IllegalArgumentException e) {
1612 // for now, drop un-parsable version when non-strict
1613 if (strict) throw e;
1614 }
1615 if (v == null) {
1616 return requires(ms, mn);
1617 } else {
1618 return requires(ms, mn, v);
1619 }
1620 }
1621
1622 /**
1623 * Adds a dependence on a module with the given (and possibly empty)
1624 * set of modifiers.
1625 *
1626 * @param ms
1627 * The set of modifiers
1628 * @param mn
1629 * The module name
1630 *
1631 * @return This builder
1632 *
1633 * @throws IllegalArgumentException
1634 * If the module name is {@code null}, is not a legal module
1635 * name, or is equal to the module name that this builder
1636 * was initialized to build
1637 * @throws IllegalStateException
1638 * If the dependence on the module has already been declared
1639 * or this builder is for an automatic module
1640 */
1641 public Builder requires(Set<Requires.Modifier> ms, String mn) {
1642 if (strict)
1643 mn = requireModuleName(mn);
1644 return requires(new Requires(ms, mn, null));
1645 }
1646
1647 /**
1648 * Adds a dependence on a module with an empty set of modifiers.
1649 *
1650 * @param mn
1651 * The module name
1652 *
1653 * @return This builder
1654 *
1655 * @throws IllegalArgumentException
1656 * If the module name is {@code null}, is not a legal module
1657 * name, or is equal to the module name that this builder
1658 * was initialized to build
1659 * @throws IllegalStateException
1660 * If the dependence on the module has already been declared
1661 * or this builder is for an automatic module
1662 */
1663 public Builder requires(String mn) {
1664 return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
1665 }
1666
1667 /**
1668 * Adds an exported package.
1669 *
1670 * @param e
1671 * The export
1672 *
1673 * @return This builder
1674 *
1675 * @throws IllegalStateException
1676 * If the {@link Exports#source package} is already declared as
1677 * exported or this builder is for an automatic module
1678 */
1679 public Builder exports(Exports e) {
1680 if (automatic) {
1681 throw new IllegalStateException("Automatic modules cannot declare"
1682 + " exported packages");
1683 }
1684 String source = e.source();
1685 if (exports.containsKey(source)) {
1686 throw new IllegalStateException("Exported package " + source
1687 + " already declared");
1688 }
1689 exports.put(source, e);
1690 packages.add(source);
1691 return this;
1692 }
1693
1694 /**
1695 * Adds an exported package with the given (and possibly empty) set of
1696 * modifiers. The package is exported to a set of target modules.
1697 *
1698 * @param ms
1699 * The set of modifiers
1700 * @param pn
1701 * The package name
1702 * @param targets
1703 * The set of target modules names
1704 *
1705 * @return This builder
1706 *
1707 * @throws IllegalArgumentException
1708 * If the package name is {@code null} or is not a legal
1709 * package name, the set of target modules is empty, or the set
1710 * of target modules contains a name that is not a legal module
1711 * name
1712 * @throws IllegalStateException
1713 * If the package is already declared as exported
1714 * or this builder is for an automatic module
1715 */
1716 public Builder exports(Set<Exports.Modifier> ms,
1717 String pn,
1718 Set<String> targets)
1719 {
1720 Exports e = new Exports(ms, pn, targets);
1721
1722 // check targets
1723 targets = e.targets();
1724 if (targets.isEmpty())
1725 throw new IllegalArgumentException("Empty target set");
1726 if (strict) {
1727 requirePackageName(e.source());
1728 targets.stream().forEach(Checks::requireModuleName);
1729 }
1730 return exports(e);
1731 }
1732
1733 /**
1734 * Adds an exported package with the given (and possibly empty) set of
1735 * modifiers. The package is exported to all modules.
1736 *
1737 * @param ms
1738 * The set of modifiers
1739 * @param pn
1740 * The package name
1741 *
1742 * @return This builder
1743 *
1744 * @throws IllegalArgumentException
1745 * If the package name is {@code null} or is not a legal
1746 * package name
1747 * @throws IllegalStateException
1748 * If the package is already declared as exported
1749 * or this builder is for an automatic module
1750 */
1751 public Builder exports(Set<Exports.Modifier> ms, String pn) {
1752 if (strict) {
1753 requirePackageName(pn);
1754 }
1755 Exports e = new Exports(ms, pn, Collections.emptySet());
1756 return exports(e);
1757 }
1758
1759 /**
1760 * Adds an exported package. The package is exported to a set of target
1761 * modules.
1762 *
1763 * @param pn
1764 * The package name
1765 * @param targets
1766 * The set of target modules names
1767 *
1768 * @return This builder
1769 *
1770 * @throws IllegalArgumentException
1771 * If the package name is {@code null} or is not a legal
1772 * package name, the set of target modules is empty, or the set
1773 * of target modules contains a name that is not a legal module
1774 * name
1775 * @throws IllegalStateException
1776 * If the package is already declared as exported
1777 * or this builder is for an automatic module
1778 */
1779 public Builder exports(String pn, Set<String> targets) {
1780 return exports(Collections.emptySet(), pn, targets);
1781 }
1782
1783 /**
1784 * Adds an exported package. The package is exported to all modules.
1785 *
1786 * @param pn
1787 * The package name
1788 *
1789 * @return This builder
1790 *
1791 * @throws IllegalArgumentException
1792 * If the package name is {@code null} or is not a legal
1793 * package name
1794 * @throws IllegalStateException
1795 * If the package is already declared as exported
1796 * or this builder is for an automatic module
1797 */
1798 public Builder exports(String pn) {
1799 return exports(Collections.emptySet(), pn);
1800 }
1801
1802 /**
1803 * Adds an open package.
1804 *
1805 * @param obj
1806 * The {@code Opens} object
1807 *
1808 * @return This builder
1809 *
1810 * @throws IllegalStateException
1811 * If the package is already declared as open, or this is a
1812 * builder for an open module or automatic module
1813 */
1814 public Builder opens(Opens obj) {
1815 if (open || automatic) {
1816 throw new IllegalStateException("Open or automatic modules cannot"
1817 + " declare open packages");
1818 }
1819 String source = obj.source();
1820 if (opens.containsKey(source)) {
1821 throw new IllegalStateException("Open package " + source
1822 + " already declared");
1823 }
1824 opens.put(source, obj);
1825 packages.add(source);
1826 return this;
1827 }
1828
1829
1830 /**
1831 * Adds an open package with the given (and possibly empty) set of
1832 * modifiers. The package is open to a set of target modules.
1833 *
1834 * @param ms
1835 * The set of modifiers
1836 * @param pn
1837 * The package name
1838 * @param targets
1839 * The set of target modules names
1840 *
1841 * @return This builder
1842 *
1843 * @throws IllegalArgumentException
1844 * If the package name is {@code null} or is not a legal
1845 * package name, the set of target modules is empty, or the set
1846 * of target modules contains a name that is not a legal module
1847 * name
1848 * @throws IllegalStateException
1849 * If the package is already declared as open, or this is a
1850 * builder for an open module or automatic module
1851 */
1852 public Builder opens(Set<Opens.Modifier> ms,
1853 String pn,
1854 Set<String> targets)
1855 {
1856 Opens opens = new Opens(ms, pn, targets);
1857
1858 // check targets
1859 targets = opens.targets();
1860 if (targets.isEmpty())
1861 throw new IllegalArgumentException("Empty target set");
1862 if (strict) {
1863 requirePackageName(opens.source());
1864 targets.stream().forEach(Checks::requireModuleName);
1865 }
1866 return opens(opens);
1867 }
1868
1869 /**
1870 * Adds an open package with the given (and possibly empty) set of
1871 * modifiers. The package is open to all modules.
1872 *
1873 * @param ms
1874 * The set of modifiers
1875 * @param pn
1876 * The package name
1877 *
1878 * @return This builder
1879 *
1880 * @throws IllegalArgumentException
1881 * If the package name is {@code null} or is not a legal
1882 * package name
1883 * @throws IllegalStateException
1884 * If the package is already declared as open, or this is a
1885 * builder for an open module or automatic module
1886 */
1887 public Builder opens(Set<Opens.Modifier> ms, String pn) {
1888 if (strict) {
1889 requirePackageName(pn);
1890 }
1891 Opens e = new Opens(ms, pn, Collections.emptySet());
1892 return opens(e);
1893 }
1894
1895 /**
1896 * Adds an open package. The package is open to a set of target modules.
1897 *
1898 * @param pn
1899 * The package name
1900 * @param targets
1901 * The set of target modules names
1902 *
1903 * @return This builder
1904 *
1905 * @throws IllegalArgumentException
1906 * If the package name is {@code null} or is not a legal
1907 * package name, the set of target modules is empty, or the set
1908 * of target modules contains a name that is not a legal module
1909 * name
1910 * @throws IllegalStateException
1911 * If the package is already declared as open, or this is a
1912 * builder for an open module or automatic module
1913 */
1914 public Builder opens(String pn, Set<String> targets) {
1915 return opens(Collections.emptySet(), pn, targets);
1916 }
1917
1918 /**
1919 * Adds an open package. The package is open to all modules.
1920 *
1921 * @param pn
1922 * The package name
1923 *
1924 * @return This builder
1925 *
1926 * @throws IllegalArgumentException
1927 * If the package name is {@code null} or is not a legal
1928 * package name
1929 * @throws IllegalStateException
1930 * If the package is already declared as open, or this is a
1931 * builder for an open module or automatic module
1932 */
1933 public Builder opens(String pn) {
1934 return opens(Collections.emptySet(), pn);
1935 }
1936
1937 /**
1938 * Adds a service dependence.
1939 *
1940 * @param service
1941 * The service type
1942 *
1943 * @return This builder
1944 *
1945 * @throws IllegalArgumentException
1946 * If the service type is {@code null} or not a qualified name of
1947 * a class in a named package
1948 * @throws IllegalStateException
1949 * If a dependency on the service type has already been declared
1950 * or this is a builder for an an automatic module
1951 */
1952 public Builder uses(String service) {
1953 if (automatic)
1954 throw new IllegalStateException("Automatic modules can not declare"
1955 + " service dependences");
1956 if (uses.contains(requireServiceTypeName(service)))
1957 throw new IllegalStateException("Dependence upon service "
1958 + service + " already declared");
1959 uses.add(service);
1960 return this;
1961 }
1962
1963 /**
1964 * Provides a service with one or more implementations. The package for
1965 * each {@link Provides#providers provider} (or provider factory) is
1966 * added to the module if not already added.
1967 *
1968 * @param p
1969 * The provides
1970 *
1971 * @return This builder
1972 *
1973 * @throws IllegalStateException
1974 * If the providers for the service type have already been
1975 * declared
1976 */
1977 public Builder provides(Provides p) {
1978 String service = p.service();
1979 if (provides.containsKey(service))
1980 throw new IllegalStateException("Providers of service "
1981 + service + " already declared");
1982 provides.put(service, p);
1983 p.providers().forEach(name -> packages.add(packageName(name)));
1984 return this;
1985 }
1986
1987 /**
1988 * Provides implementations of a service. The package for each provider
1989 * (or provider factory) is added to the module if not already added.
1990 *
1991 * @param service
1992 * The service type
1993 * @param providers
1994 * The list of provider or provider factory class names
1995 *
1996 * @return This builder
1997 *
1998 * @throws IllegalArgumentException
1999 * If the service type or any of the provider class names is
2000 * {@code null} or not a qualified name of a class in a named
2001 * package, or the list of provider class names is empty
2002 * @throws IllegalStateException
2003 * If the providers for the service type have already been
2004 * declared
2005 */
2006 public Builder provides(String service, List<String> providers) {
2007 Provides p = new Provides(service, providers);
2008
2009 // check providers after the set has been copied.
2010 List<String> providerNames = p.providers();
2011 if (providerNames.isEmpty())
2012 throw new IllegalArgumentException("Empty providers set");
2013 if (strict) {
2014 requireServiceTypeName(p.service());
2015 providerNames.forEach(Checks::requireServiceProviderName);
2016 } else {
2017 // Disallow service/providers in unnamed package
2018 String pn = packageName(service);
2019 if (pn.isEmpty()) {
2020 throw new IllegalArgumentException(service
2021 + ": unnamed package");
2022 }
2023 for (String name : providerNames) {
2024 pn = packageName(name);
2025 if (pn.isEmpty()) {
2026 throw new IllegalArgumentException(name
2027 + ": unnamed package");
2028 }
2029 }
2030 }
2031 return provides(p);
2032 }
2033
2034 /**
2035 * Adds packages to the module. All packages in the set of package names
2036 * that are not in the module are added to module.
2037 *
2038 * @param pns
2039 * The (possibly empty) set of package names
2040 *
2041 * @return This builder
2042 *
2043 * @throws IllegalArgumentException
2044 * If any of the package names is {@code null} or is not a
2045 * legal package name
2046 */
2047 public Builder packages(Set<String> pns) {
2048 if (strict) {
2049 pns = new HashSet<>(pns);
2050 pns.forEach(Checks::requirePackageName);
2051 }
2052 this.packages.addAll(pns);
2053 return this;
2054 }
2055
2056 /**
2057 * Sets the module version.
2058 *
2059 * @param v
2060 * The version
2061 *
2062 * @return This builder
2063 */
2064 public Builder version(Version v) {
2065 version = requireNonNull(v);
2066 return this;
2067 }
2068
2069 /**
2070 * Sets the module version.
2071 *
2072 * @param vs
2073 * The version string to parse
2074 *
2075 * @return This builder
2076 *
2077 * @throws IllegalArgumentException
2078 * If {@code vs} is {@code null} or cannot be parsed as a
2079 * version string
2080 *
2081 * @see Version#parse(String)
2082 */
2083 public Builder version(String vs) {
2084 Version v;
2085 if (strict) {
2086 v = Version.parse(vs);
2087 } else {
2088 try {
2089 v = Version.parse(vs);
2090 } catch (IllegalArgumentException ignore) {
2091 // for now, ignore when non-strict
2092 return this;
2093 }
2094 }
2095 return version(v);
2096 }
2097
2098 /**
2099 * Sets the module main class. The package for the main class is added
2100 * to the module if not already added.
2101 *
2102 * @param mc
2103 * The module main class
2104 *
2105 * @return This builder
2106 *
2107 * @throws IllegalArgumentException
2108 * If {@code mainClass} is {@code null} or not a qualified
2109 * name of a class in a named package
2110 */
2111 public Builder mainClass(String mc) {
2112 String pn;
2113 if (strict) {
2114 mc = requireQualifiedClassName("main class name", mc);
2115 pn = packageName(mc);
2116 assert !pn.isEmpty();
2117 } else {
2118 // Disallow main class in unnamed package
2119 pn = packageName(mc);
2120 if (pn.isEmpty()) {
2121 throw new IllegalArgumentException(mc + ": unnamed package");
2122 }
2123 }
2124 mainClass = mc;
2125 packages.add(pn);
2126 return this;
2127 }
2128
2129 /**
2130 * Sets the operating system name.
2131 *
2132 * @param name
2133 * The operating system name
2134 *
2135 * @return This builder
2136 *
2137 * @throws IllegalArgumentException
2138 * If {@code name} is {@code null} or the empty String
2139 */
2140 public Builder osName(String name) {
2141 if (name == null || name.isEmpty())
2142 throw new IllegalArgumentException("OS name is null or empty");
2143 osName = name;
2144 return this;
2145 }
2146
2147 /**
2148 * Sets the operating system architecture.
2149 *
2150 * @param arch
2151 * The operating system architecture
2152 *
2153 * @return This builder
2154 *
2155 * @throws IllegalArgumentException
2156 * If {@code name} is {@code null} or the empty String
2157 */
2158 public Builder osArch(String arch) {
2159 if (arch == null || arch.isEmpty())
2160 throw new IllegalArgumentException("OS arch is null or empty");
2161 osArch = arch;
2162 return this;
2163 }
2164
2165 /**
2166 * Sets the operating system version.
2167 *
2168 * @param version
2169 * The operating system version
2170 *
2171 * @return This builder
2172 *
2173 * @throws IllegalArgumentException
2174 * If {@code name} is {@code null} or the empty String
2175 */
2176 public Builder osVersion(String version) {
2177 if (version == null || version.isEmpty())
2178 throw new IllegalArgumentException("OS version is null or empty");
2179 osVersion = version;
2180 return this;
2181 }
2182
2183 /**
2184 * Builds and returns a {@code ModuleDescriptor} from its components.
2185 *
2186 * <p> The module will require "{@code java.base}" even if the dependence
2187 * has not been declared (the exception is when building a module named
2188 * "{@code java.base}" as it cannot require itself). The dependence on
2189 * "{@code java.base}" will have the {@link
2190 * java.lang.module.ModuleDescriptor.Requires.Modifier#MANDATED MANDATED}
2191 * modifier if the dependence was not declared. </p>
2192 *
2193 * @return The module descriptor
2194 */
2195 public ModuleDescriptor build() {
2196 Set<Requires> requires = new HashSet<>(this.requires.values());
2197 Set<Exports> exports = new HashSet<>(this.exports.values());
2198 Set<Opens> opens = new HashSet<>(this.opens.values());
2199
2200 // add dependency on java.base
2201 if (strict
2202 && !name.equals("java.base")
2203 && !this.requires.containsKey("java.base")) {
2204 requires.add(new Requires(Set.of(Requires.Modifier.MANDATED),
2205 "java.base",
2206 null));
2207 }
2208
2209 Set<Provides> provides = new HashSet<>(this.provides.values());
2210
2211 return new ModuleDescriptor(name,
2212 version,
2213 modifiers,
2214 requires,
2215 exports,
2216 opens,
2217 uses,
2218 provides,
2219 packages,
2220 mainClass,
2221 osName,
2222 osArch,
2223 osVersion);
2224 }
2225
2226 }
2227
2228 /**
2229 * Compares this module descriptor to another.
2230 *
2231 * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
2232 * module names lexicographically. Where the module names are equal then the
2233 * module versions are compared. When comparing the module versions then a
2234 * module descriptor with a version is considered to succeed a module
2235 * descriptor that does not have a version. Where the module names are equal
2236 * and the versions are equal (or not present in both), then the set of
2237 * modifiers are compared. Sets of modifiers are compared by comparing
2238 * a <em>binary value</em> computed for each set. If a modifier is present
2239 * in the set then the bit at the position of its ordinal is {@code 1}
2240 * in the binary value, otherwise {@code 0}. If the two set of modifiers
2241 * are also equal then the other components of the module descriptors are
2242 * compared in a manner that is consistent with {@code equals}. </p>
2243 *
2244 * @param that
2245 * The module descriptor to compare
2246 *
2247 * @return A negative integer, zero, or a positive integer if this module
2248 * descriptor is less than, equal to, or greater than the given
2249 * module descriptor
2250 */
2251 @Override
2252 public int compareTo(ModuleDescriptor that) {
2253 if (this == that) return 0;
2254
2255 int c = this.name().compareTo(that.name());
2256 if (c != 0) return c;
2257
2258 c = compare(this.version, that.version);
2259 if (c != 0) return c;
2260
2261 long v1 = modsValue(this.modifiers());
2262 long v2 = modsValue(that.modifiers());
2263 c = Long.compare(v1, v2);
2264 if (c != 0) return c;
2265
2266 c = compare(this.requires, that.requires);
2267 if (c != 0) return c;
2268
2269 c = compare(this.packages, that.packages);
2270 if (c != 0) return c;
2271
2272 c = compare(this.exports, that.exports);
2273 if (c != 0) return c;
2274
2275 c = compare(this.opens, that.opens);
2276 if (c != 0) return c;
2277
2278 c = compare(this.uses, that.uses);
2279 if (c != 0) return c;
2280
2281 c = compare(this.provides, that.provides);
2282 if (c != 0) return c;
2283
2284 c = compare(this.mainClass, that.mainClass);
2285 if (c != 0) return c;
2286
2287 c = compare(this.osName, that.osName);
2288 if (c != 0) return c;
2289
2290 c = compare(this.osArch, that.osArch);
2291 if (c != 0) return c;
2292
2293 c = compare(this.osVersion, that.osVersion);
2294 if (c != 0) return c;
2295
2296 return 0;
2297 }
2298
2299 /**
2300 * Tests this module descriptor for equality with the given object.
2301 *
2302 * <p> If the given object is not a {@code ModuleDescriptor} then this
2303 * method returns {@code false}. Two module descriptors are equal if each
2304 * of their corresponding components is equal. </p>
2305 *
2306 * <p> This method satisfies the general contract of the {@link
2307 * java.lang.Object#equals(Object) Object.equals} method. </p>
2308 *
2309 * @param ob
2310 * the object to which this object is to be compared
2311 *
2312 * @return {@code true} if, and only if, the given object is a module
2313 * descriptor that is equal to this module descriptor
2314 */
2315 @Override
2316 public boolean equals(Object ob) {
2317 if (ob == this)
2318 return true;
2319 if (!(ob instanceof ModuleDescriptor))
2320 return false;
2321 ModuleDescriptor that = (ModuleDescriptor)ob;
2322 return (name.equals(that.name)
2323 && modifiers.equals(that.modifiers)
2324 && requires.equals(that.requires)
2325 && Objects.equals(packages, that.packages)
2326 && exports.equals(that.exports)
2327 && opens.equals(that.opens)
2328 && uses.equals(that.uses)
2329 && provides.equals(that.provides)
2330 && Objects.equals(version, that.version)
2331 && Objects.equals(mainClass, that.mainClass)
2332 && Objects.equals(osName, that.osName)
2333 && Objects.equals(osArch, that.osArch)
2334 && Objects.equals(osVersion, that.osVersion));
2335 }
2336
2337 /**
2338 * Computes a hash code for this module descriptor.
2339 *
2340 * <p> The hash code is based upon the components of the module descriptor,
2341 * and satisfies the general contract of the {@link Object#hashCode
2342 * Object.hashCode} method. </p>
2343 *
2344 * @return The hash-code value for this module descriptor
2345 */
2346 @Override
2347 public int hashCode() {
2348 int hc = hash;
2349 if (hc == 0) {
2350 hc = name.hashCode();
2351 hc = hc * 43 + Objects.hashCode(modifiers);
2352 hc = hc * 43 + requires.hashCode();
2353 hc = hc * 43 + Objects.hashCode(packages);
2354 hc = hc * 43 + exports.hashCode();
2355 hc = hc * 43 + opens.hashCode();
2356 hc = hc * 43 + uses.hashCode();
2357 hc = hc * 43 + provides.hashCode();
2358 hc = hc * 43 + Objects.hashCode(version);
2359 hc = hc * 43 + Objects.hashCode(mainClass);
2360 hc = hc * 43 + Objects.hashCode(osName);
2361 hc = hc * 43 + Objects.hashCode(osArch);
2362 hc = hc * 43 + Objects.hashCode(osVersion);
2363 if (hc == 0)
2364 hc = -1;
2365 hash = hc;
2366 }
2367 return hc;
2368 }
2369 private transient int hash; // cached hash code
2370
2371 /**
2372 * <p> Returns a string describing the module. </p>
2373 *
2374 * @return A string describing the module
2375 */
2376 @Override
2377 public String toString() {
2378 StringBuilder sb = new StringBuilder();
2379
2380 if (isOpen())
2381 sb.append("open ");
2382 sb.append("module { name: ").append(toNameAndVersion());
2383 if (!requires.isEmpty())
2384 sb.append(", ").append(requires);
2385 if (!uses.isEmpty())
2386 sb.append(", uses: ").append(uses);
2387 if (!exports.isEmpty())
2388 sb.append(", exports: ").append(exports);
2389 if (!opens.isEmpty())
2390 sb.append(", opens: ").append(opens);
2391 if (!provides.isEmpty()) {
2392 sb.append(", provides: ").append(provides);
2393 }
2394 sb.append(" }");
2395 return sb.toString();
2396 }
2397
2398
2399 /**
2400 * Instantiates a builder to build a module descriptor.
2401 *
2402 * @param name
2403 * The module name
2404 * @param ms
2405 * The set of module modifiers
2406 *
2407 * @return A new builder
2408 *
2409 * @throws IllegalArgumentException
2410 * If the module name is {@code null} or is not a legal module
2411 * name, or the set of modifiers contains both {@link Modifier#OPEN
2412 * OPEN} and {@link Modifier#AUTOMATIC AUTOMATIC}
2413 */
2414 public static Builder newModule(String name, Set<Modifier> ms) {
2415 Set<Modifier> mods = new HashSet<>(ms);
2416 if (mods.contains(Modifier.OPEN) && mods.contains(Modifier.AUTOMATIC))
2417 throw new IllegalArgumentException("OPEN and AUTOMATIC not allowed");
2418 return new Builder(name, true, mods);
2419 }
2420
2421 /**
2422 * Instantiates a builder to build a module descriptor.
2423 *
2424 * @param name
2425 * The module name
2426 *
2427 * @return A new builder
2428 *
2429 * @throws IllegalArgumentException
2430 * If the module name is {@code null} or is not a legal module
2431 * name
2432 */
2433 public static Builder newModule(String name) {
2434 return new Builder(name, true, Set.of());
2435 }
2436
2437 /**
2438 * Instantiates a builder to build a module descriptor for an open module.
2439 *
2440 * <p> The builder for an open module cannot be used to declare any open
2441 * packages. </p>
2442 *
2443 * @param name
2444 * The module name
2445 *
2446 * @return A new builder that builds an open module
2447 *
2448 * @throws IllegalArgumentException
2449 * If the module name is {@code null} or is not a legal module
2450 * name
2451 */
2452 public static Builder newOpenModule(String name) {
2453 return new Builder(name, true, Set.of(Modifier.OPEN));
2454 }
2455
2456 /**
2457 * Instantiates a builder to build a module descriptor for an automatic
2458 * module.
2459 *
2460 * <p> The builder for an automatic module cannot be used to declare module
2461 * or service dependences. It also cannot be used to declare any exported
2462 * or open packages. </p>
2463 *
2464 * @param name
2465 * The module name
2466 *
2467 * @return A new builder that builds an automatic module
2468 *
2469 * @throws IllegalArgumentException
2470 * If the module name is {@code null} or is not a legal module
2471 * name
2472 *
2473 * @see ModuleFinder#of(Path[])
2474 */
2475 public static Builder newAutomaticModule(String name) {
2476 return new Builder(name, true, Set.of(Modifier.AUTOMATIC));
2477 }
2478
2479
2480 /**
2481 * Reads the binary form of a module declaration from an input stream
2482 * as a module descriptor.
2483 *
2484 * <p> If the descriptor encoded in the input stream does not indicate a
2485 * set of packages in the module then the {@code packageFinder} will be
2486 * invoked. The set of packages that the {@code packageFinder} returns
2487 * must include all the packages that the module exports, opens, as well
2488 * as the packages of the service implementations that the module provides,
2489 * and the package of the main class (if the module has a main class). If
2490 * the {@code packageFinder} throws an {@link UncheckedIOException} then
2491 * {@link IOException} cause will be re-thrown. </p>
2492 *
2493 * <p> If there are bytes following the module descriptor then it is
2494 * implementation specific as to whether those bytes are read, ignored,
2495 * or reported as an {@code InvalidModuleDescriptorException}. If this
2496 * method fails with an {@code InvalidModuleDescriptorException} or {@code
2497 * IOException} then it may do so after some, but not all, bytes have
2498 * been read from the input stream. It is strongly recommended that the
2499 * stream be promptly closed and discarded if an exception occurs. </p>
2500 *
2501 * @apiNote The {@code packageFinder} parameter is for use when reading
2502 * module descriptors from legacy module-artifact formats that do not
2503 * record the set of packages in the descriptor itself.
2504 *
2505 * @param in
2506 * The input stream
2507 * @param packageFinder
2508 * A supplier that can produce the set of packages
2509 *
2510 * @return The module descriptor
2511 *
2512 * @throws InvalidModuleDescriptorException
2513 * If an invalid module descriptor is detected or the set of
2514 * packages returned by the {@code packageFinder} does not include
2515 * all of the packages obtained from the module descriptor
2516 * @throws IOException
2517 * If an I/O error occurs reading from the input stream or {@code
2518 * UncheckedIOException} is thrown by the package finder
2519 */
2520 public static ModuleDescriptor read(InputStream in,
2521 Supplier<Set<String>> packageFinder)
2522 throws IOException
2523 {
2524 return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
2525 }
2526
2527 /**
2528 * Reads the binary form of a module declaration from an input stream as a
2529 * module descriptor. This method works exactly as specified by the 2-arg
2530 * {@link #read(InputStream,Supplier) read} method with the exception that
2531 * a packager finder is not used to find additional packages when the
2532 * module descriptor read from the stream does not indicate the set of
2533 * packages.
2534 *
2535 * @param in
2536 * The input stream
2537 *
2538 * @return The module descriptor
2539 *
2540 * @throws InvalidModuleDescriptorException
2541 * If an invalid module descriptor is detected
2542 * @throws IOException
2543 * If an I/O error occurs reading from the input stream
2544 */
2545 public static ModuleDescriptor read(InputStream in) throws IOException {
2546 return ModuleInfo.read(in, null).descriptor();
2547 }
2548
2549 /**
2550 * Reads the binary form of a module declaration from a byte buffer
2551 * as a module descriptor.
2552 *
2553 * <p> If the descriptor encoded in the byte buffer does not indicate a
2554 * set of packages in the module then the {@code packageFinder} will be
2555 * invoked. The set of packages that the {@code packageFinder} returns
2556 * must include all the packages that the module exports, opens, as well
2557 * as the packages of the service implementations that the module provides,
2558 * and the package of the main class (if the module has a main class). If
2559 * the {@code packageFinder} throws an {@link UncheckedIOException} then
2560 * {@link IOException} cause will be re-thrown. </p>
2561 *
2562 * <p> The module descriptor is read from the buffer stating at index
2563 * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
2564 * position} when this method is invoked. Upon return the buffer's position
2565 * will be equal to {@code p + n} where {@code n} is the number of bytes
2566 * read from the buffer. </p>
2567 *
2568 * <p> If there are bytes following the module descriptor then it is
2569 * implementation specific as to whether those bytes are read, ignored,
2570 * or reported as an {@code InvalidModuleDescriptorException}. If this
2571 * method fails with an {@code InvalidModuleDescriptorException} then it
2572 * may do so after some, but not all, bytes have been read. </p>
2573 *
2574 * @apiNote The {@code packageFinder} parameter is for use when reading
2575 * module descriptors from legacy module-artifact formats that do not
2576 * record the set of packages in the descriptor itself.
2577 *
2578 * @param bb
2579 * The byte buffer
2580 * @param packageFinder
2581 * A supplier that can produce the set of packages
2582 *
2583 * @return The module descriptor
2584 *
2585 * @throws InvalidModuleDescriptorException
2586 * If an invalid module descriptor is detected or the set of
2587 * packages returned by the {@code packageFinder} does not include
2588 * all of the packages obtained from the module descriptor
2589 */
2590 public static ModuleDescriptor read(ByteBuffer bb,
2591 Supplier<Set<String>> packageFinder)
2592 {
2593 return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
2594 }
2595
2596 /**
2597 * Reads the binary form of a module declaration from a byte buffer as a
2598 * module descriptor. This method works exactly as specified by the 2-arg
2599 * {@link #read(ByteBuffer,Supplier) read} method with the exception that a
2600 * packager finder is not used to find additional packages when the module
2601 * descriptor encoded in the buffer does not indicate the set of packages.
2602 *
2603 * @param bb
2604 * The byte buffer
2605 *
2606 * @return The module descriptor
2607 *
2608 * @throws InvalidModuleDescriptorException
2609 * If an invalid module descriptor is detected
2610 */
2611 public static ModuleDescriptor read(ByteBuffer bb) {
2612 return ModuleInfo.read(bb, null).descriptor();
2613 }
2614
2615 private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
2616 if (map.isEmpty()) {
2617 return Collections.emptyMap();
2618 } else if (map.size() == 1) {
2619 Map.Entry<K, V> entry = map.entrySet().iterator().next();
2620 return Collections.singletonMap(entry.getKey(), entry.getValue());
2621 } else {
2622 return Collections.unmodifiableMap(map);
2623 }
2624 }
2625
2626 private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) {
2627 if (set.isEmpty()) {
2628 return Collections.emptySet();
2629 } else if (set.size() == 1) {
2630 return Collections.singleton(set.iterator().next());
2631 } else {
2632 return Collections.unmodifiableSet(set);
2633 }
2634 }
2635
2636 private static String packageName(String cn) {
2637 int index = cn.lastIndexOf('.');
2638 return (index == -1) ? "" : cn.substring(0, index);
2639 }
2640
2641 /**
2642 * Returns a string containing the given set of modifiers and label.
2643 */
2644 private static <M> String toString(Set<M> mods, String what) {
2645 return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
2646 Stream.of(what)))
2647 .collect(Collectors.joining(" "));
2648 }
2649
2650 private static <T extends Object & Comparable<? super T>>
2651 int compare(T obj1, T obj2) {
2652 if (obj1 != null) {
2653 return (obj2 != null) ? obj1.compareTo(obj2) : 1;
2654 } else {
2655 return (obj2 == null) ? 0 : -1;
2656 }
2657 }
2658
2659 /**
2660 * Compares two sets of {@code Comparable} objects.
2661 */
2662 private static <T extends Object & Comparable<? super T>>
2663 int compare(Set<T> s1, Set<T> s2) {
2664 Iterator<T> iterator1 = new TreeSet<>(s1).iterator();
2665 Iterator<T> iterator2 = new TreeSet<>(s2).iterator();
2666 while (iterator1.hasNext()) {
2667 if (!iterator2.hasNext())
2668 return 1; // s1 has more elements
2669 T e1 = iterator1.next();
2670 T e2 = iterator2.next();
2671 int c = e1.compareTo(e2);
2672 if (c != 0)
2673 return c;
2674 }
2675 if (iterator2.hasNext()) {
2676 return -1; // s2 has more elements
2677 } else {
2678 return 0;
2679 }
2680 }
2681
2682 private static <E extends Enum<E>> long modsValue(Set<E> set) {
2683 long value = 0;
2684 for (Enum<E> e : set) {
2685 value += 1 << e.ordinal();
2686 }
2687 return value;
2688 }
2689
2690 static {
2691 /**
2692 * Setup the shared secret to allow code in other packages access
2693 * private package methods in java.lang.module.
2694 */
2695 jdk.internal.misc.SharedSecrets
2696 .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
2697 @Override
2698 public Builder newModuleBuilder(String mn,
2699 boolean strict,
2700 Set<ModuleDescriptor.Modifier> modifiers) {
2701 return new Builder(mn, strict, modifiers);
2702 }
2703
2704 @Override
2705 public Set<String> packages(ModuleDescriptor.Builder builder) {
2706 return builder.packages();
2707 }
2708
2709 @Override
2710 public void requires(ModuleDescriptor.Builder builder,
2711 Set<Requires.Modifier> ms,
2712 String mn,
2713 String compiledVersion) {
2714 builder.requires(ms, mn, compiledVersion);
2715 }
2716
2717 @Override
2718 public Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v) {
2719 return new Requires(ms, mn, v, true);
2720 }
2721
2722 @Override
2723 public Exports newExports(Set<Exports.Modifier> ms, String source) {
2724 return new Exports(ms, source, Collections.emptySet(), true);
2725 }
2726
2727 @Override
2728 public Exports newExports(Set<Exports.Modifier> ms,
2729 String source,
2730 Set<String> targets) {
2731 return new Exports(ms, source, targets, true);
2732 }
2733
2734 @Override
2735 public Opens newOpens(Set<Opens.Modifier> ms,
2736 String source,
2737 Set<String> targets) {
2738 return new Opens(ms, source, targets, true);
2739 }
2740
2741 @Override
2742 public Opens newOpens(Set<Opens.Modifier> ms, String source) {
2743 return new Opens(ms, source, Collections.emptySet(), true);
2744 }
2745
2746 @Override
2747 public Provides newProvides(String service, List<String> providers) {
2748 return new Provides(service, providers, true);
2749 }
2750
2751 @Override
2752 public ModuleDescriptor newModuleDescriptor(String name,
2753 Version version,
2754 Set<ModuleDescriptor.Modifier> modifiers,
2755 Set<Requires> requires,
2756 Set<Exports> exports,
2757 Set<Opens> opens,
2758 Set<String> uses,
2759 Set<Provides> provides,
2760 Set<String> packages,
2761 String mainClass,
2762 String osName,
2763 String osArch,
2764 String osVersion,
2765 int hashCode) {
2766 return new ModuleDescriptor(name,
2767 version,
2768 modifiers,
2769 requires,
2770 exports,
2771 opens,
2772 uses,
2773 provides,
2774 packages,
2775 mainClass,
2776 osName,
2777 osArch,
2778 osVersion,
2779 hashCode,
2780 false);
2781 }
2782
2783 @Override
2784 public Configuration resolveAndBind(ModuleFinder finder,
2785 Collection<String> roots,
2786 boolean check,
2787 PrintStream traceOutput)
2788 {
2789 return Configuration.resolveAndBind(finder, roots, check, traceOutput);
2790 }
2791 });
2792 }
2793
2794 }
|