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.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.EnumSet;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.Map;
44 import java.util.Objects;
45 import java.util.Optional;
46 import java.util.Set;
47 import java.util.function.Supplier;
48 import java.util.stream.Collectors;
49 import java.util.stream.Stream;
50
51 import static jdk.internal.module.Checks.*;
52 import static java.util.Objects.*;
53
54 import jdk.internal.module.Checks;
55 import jdk.internal.module.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.Module Module}'s {@link java.lang.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.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 * @spec JPMS
104 */
105 public enum Modifier {
106 /**
107 * An open module. An open module does not declare any open packages
108 * but the resulting module is treated as if all packages are open.
109 */
110 OPEN,
111
112 /**
113 * An automatic module. An automatic module is treated as if it exports
114 * and opens all packages.
115 *
116 * @apiNote This modifier does not correspond to a module flag in the
117 * binary form of a module declaration ({@code module-info.class}).
118 */
119 AUTOMATIC,
120
121 /**
122 * The module was not explicitly or implicitly declared.
123 */
124 SYNTHETIC,
125
126 /**
127 * The module was implicitly declared.
128 */
129 MANDATED;
130 }
131
132
133 /**
134 * <p> A dependence upon a module </p>
135 *
136 * @see ModuleDescriptor#requires()
137 * @since 9
138 * @spec JPMS
139 */
140
141 public final static class Requires
142 implements Comparable<Requires>
143 {
144
145 /**
146 * A modifier on a module dependence.
147 *
148 * @see Requires#modifiers()
149 * @since 9
150 * @spec JPMS
151 */
152 public enum Modifier {
153
154 /**
155 * The dependence causes any module which depends on the <i>current
156 * module</i> to have an implicitly declared dependence on the module
157 * named by the {@code Requires}.
158 */
159 TRANSITIVE,
160
161 /**
162 * The dependence is mandatory in the static phase, during compilation,
163 * but is optional in the dynamic phase, during execution.
164 */
165 STATIC,
166
167 /**
168 * The dependence was not explicitly or implicitly declared in the
169 * source of the module declaration.
170 */
171 SYNTHETIC,
172
173 /**
174 * The dependence was implicitly declared in the source of the module
175 * declaration.
176 */
177 MANDATED;
178
179 }
180
181 private final Set<Modifier> mods;
182 private final String name;
183 private final Version compiledVersion;
184 private final String rawCompiledVersion;
185
186 private Requires(Set<Modifier> ms, String mn, Version v, String vs) {
187 assert v == null || vs == null;
188 this.mods = Set.copyOf(ms);
189 this.name = mn;
190 this.compiledVersion = v;
191 this.rawCompiledVersion = vs;
192 }
193
194 private Requires(Set<Modifier> ms, String mn, Version v, boolean unused) {
195 this.mods = ms;
196 this.name = mn;
197 this.compiledVersion = v;
198 this.rawCompiledVersion = null;
199 }
200
201 /**
202 * Returns the set of modifiers.
203 *
204 * @return A possibly-empty unmodifiable set of modifiers
205 */
206 public Set<Modifier> modifiers() {
207 return mods;
208 }
209
210 /**
211 * Return the module name.
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 * or an empty {@code Optional} if no version was recorded or
224 * the version string recorded is {@linkplain Version#parse(String)
225 * unparseable}
226 */
227 public Optional<Version> compiledVersion() {
228 return Optional.ofNullable(compiledVersion);
229 }
230
231 /**
232 * Returns the string with the possibly-unparseable version of the module
233 * if recorded at compile-time.
234 *
235 * @return The string containing the version of the module if recorded
236 * at compile-time, or an empty {@code Optional} if no version
237 * was recorded
238 *
239 * @see #compiledVersion()
240 */
241 public Optional<String> rawCompiledVersion() {
242 if (compiledVersion != null) {
243 return Optional.of(compiledVersion.toString());
244 } else {
245 return Optional.ofNullable(rawCompiledVersion);
246 }
247 }
248
249 /**
250 * Compares this module dependence to another.
251 *
252 * <p> Two {@code Requires} objects are compared by comparing their
253 * module names lexicographically. Where the module names are equal
254 * then the sets of modifiers are compared in the same way that
255 * module modifiers are compared (see {@link ModuleDescriptor#compareTo
256 * ModuleDescriptor.compareTo}). Where the module names are equal and
257 * the set of modifiers are equal then the version of the modules
258 * recorded at compile-time are compared. When comparing the versions
259 * recorded at compile-time then a dependence that has a recorded
260 * version is considered to succeed a dependence that does not have a
261 * recorded version. If both recorded versions are {@linkplain
262 * Version#parse(String) unparseable} then the {@linkplain
263 * #rawCompiledVersion() raw version strings} are compared
264 * lexicographically. </p>
265 *
266 * @param that
267 * The module dependence to compare
268 *
269 * @return A negative integer, zero, or a positive integer if this module
270 * dependence is less than, equal to, or greater than the given
271 * module dependence
272 */
273 @Override
274 public int compareTo(Requires that) {
275 if (this == that) return 0;
276
277 int c = this.name().compareTo(that.name());
278 if (c != 0) return c;
279
280 // modifiers
281 long v1 = modsValue(this.modifiers());
282 long v2 = modsValue(that.modifiers());
283 c = Long.compare(v1, v2);
284 if (c != 0) return c;
285
286 // compiledVersion
287 c = compare(this.compiledVersion, that.compiledVersion);
288 if (c != 0) return c;
289
290 // rawCompiledVersion
291 c = compare(this.rawCompiledVersion, that.rawCompiledVersion);
292 if (c != 0) return c;
293
294 return 0;
295 }
296
297 /**
298 * Tests this module dependence for equality with the given object.
299 *
300 * <p> If the given object is not a {@code Requires} then this method
301 * returns {@code false}. Two module dependence objects are equal if
302 * the module names are equal, set of modifiers are equal, and the
303 * compiled version of both modules is equal or not recorded for
304 * both modules. </p>
305 *
306 * <p> This method satisfies the general contract of the {@link
307 * java.lang.Object#equals(Object) Object.equals} method. </p>
308 *
309 * @param ob
310 * the object to which this object is to be compared
311 *
312 * @return {@code true} if, and only if, the given object is a module
313 * dependence that is equal to this module dependence
314 */
315 @Override
316 public boolean equals(Object ob) {
317 if (!(ob instanceof Requires))
318 return false;
319 Requires that = (Requires)ob;
320 return name.equals(that.name) && mods.equals(that.mods)
321 && Objects.equals(compiledVersion, that.compiledVersion)
322 && Objects.equals(rawCompiledVersion, that.rawCompiledVersion);
323 }
324
325 /**
326 * Computes a hash code for this module dependence.
327 *
328 * <p> The hash code is based upon the module name, modifiers, and the
329 * module version if recorded at compile time. It satisfies the general
330 * contract of the {@link Object#hashCode Object.hashCode} method. </p>
331 *
332 * @return The hash-code value for this module dependence
333 */
334 @Override
335 public int hashCode() {
336 int hash = name.hashCode() * 43 + mods.hashCode();
337 if (compiledVersion != null)
338 hash = hash * 43 + compiledVersion.hashCode();
339 if (rawCompiledVersion != null)
340 hash = hash * 43 + rawCompiledVersion.hashCode();
341 return hash;
342 }
343
344 /**
345 * Returns a string describing this module dependence.
346 *
347 * @return A string describing this module dependence
348 */
349 @Override
350 public String toString() {
351 String what;
352 if (compiledVersion != null) {
353 what = name() + " (@" + compiledVersion + ")";
354 } else {
355 what = name();
356 }
357 return ModuleDescriptor.toString(mods, what);
358 }
359 }
360
361
362
363 /**
364 * <p> A package exported by a module, may be qualified or unqualified. </p>
365 *
366 * @see ModuleDescriptor#exports()
367 * @since 9
368 * @spec JPMS
369 */
370
371 public final static class Exports
372 implements Comparable<Exports>
373 {
374
375 /**
376 * A modifier on an exported package.
377 *
378 * @see Exports#modifiers()
379 * @since 9
380 * @spec JPMS
381 */
382 public enum Modifier {
383
384 /**
385 * The export was not explicitly or implicitly declared in the
386 * source of the module declaration.
387 */
388 SYNTHETIC,
389
390 /**
391 * The export was implicitly declared in the source of the module
392 * declaration.
393 */
394 MANDATED;
395
396 }
397
398 private final Set<Modifier> mods;
399 private final String source;
400 private final Set<String> targets; // empty if unqualified export
401
402 /**
403 * Constructs an export
404 */
405 private Exports(Set<Modifier> ms, String source, Set<String> targets) {
406 this.mods = Set.copyOf(ms);
407 this.source = source;
408 this.targets = Set.copyOf(targets);
409 }
410
411 private Exports(Set<Modifier> ms,
412 String source,
413 Set<String> targets,
414 boolean unused) {
415 this.mods = ms;
416 this.source = source;
417 this.targets = targets;
418 }
419
420 /**
421 * Returns the set of modifiers.
422 *
423 * @return A possibly-empty unmodifiable set of modifiers
424 */
425 public Set<Modifier> modifiers() {
426 return mods;
427 }
428
429 /**
430 * Returns {@code true} if this is a qualified export.
431 *
432 * @return {@code true} if this is a qualified export
433 */
434 public boolean isQualified() {
435 return !targets.isEmpty();
436 }
437
438 /**
439 * Returns the package name.
440 *
441 * @return The package name
442 */
443 public String source() {
444 return source;
445 }
446
447 /**
448 * For a qualified export, returns the non-empty and immutable set
449 * of the module names to which the package is exported. For an
450 * unqualified export, returns an empty set.
451 *
452 * @return The set of target module names or for an unqualified
453 * export, an empty set
454 */
455 public Set<String> targets() {
456 return targets;
457 }
458
459 /**
460 * Compares this module export to another.
461 *
462 * <p> Two {@code Exports} objects are compared by comparing the package
463 * names lexicographically. Where the packages names are equal then the
464 * sets of modifiers are compared in the same way that module modifiers
465 * are compared (see {@link ModuleDescriptor#compareTo
466 * ModuleDescriptor.compareTo}). Where the package names are equal and
467 * the set of modifiers are equal then the set of target modules are
468 * compared. This is done by sorting the names of the target modules
469 * in ascending order, and according to their natural ordering, and then
470 * comparing the corresponding elements lexicographically. Where the
471 * sets differ in size, and the larger set contains all elements of the
472 * smaller set, then the larger set is considered to succeed the smaller
473 * set. </p>
474 *
475 * @param that
476 * The module export to compare
477 *
478 * @return A negative integer, zero, or a positive integer if this module
479 * export is less than, equal to, or greater than the given
480 * export dependence
481 */
482 @Override
483 public int compareTo(Exports that) {
484 if (this == that) return 0;
485
486 int c = source.compareTo(that.source);
487 if (c != 0)
488 return c;
489
490 // modifiers
491 long v1 = modsValue(this.modifiers());
492 long v2 = modsValue(that.modifiers());
493 c = Long.compare(v1, v2);
494 if (c != 0)
495 return c;
496
497 // targets
498 c = compare(targets, that.targets);
499 if (c != 0)
500 return c;
501
502 return 0;
503 }
504
505 /**
506 * Computes a hash code for this module export.
507 *
508 * <p> The hash code is based upon the modifiers, the package name,
509 * and for a qualified export, the set of modules names to which the
510 * package is exported. It satisfies the general contract of the
511 * {@link Object#hashCode Object.hashCode} method.
512 *
513 * @return The hash-code value for this module export
514 */
515 @Override
516 public int hashCode() {
517 int hash = mods.hashCode();
518 hash = hash * 43 + source.hashCode();
519 return hash * 43 + targets.hashCode();
520 }
521
522 /**
523 * Tests this module export for equality with the given object.
524 *
525 * <p> If the given object is not an {@code Exports} then this method
526 * returns {@code false}. Two module exports objects are equal if their
527 * set of modifiers is equal, the package names are equal and the set
528 * of target module names is equal. </p>
529 *
530 * <p> This method satisfies the general contract of the {@link
531 * java.lang.Object#equals(Object) Object.equals} method. </p>
532 *
533 * @param ob
534 * the object to which this object is to be compared
535 *
536 * @return {@code true} if, and only if, the given object is a module
537 * dependence that is equal to this module dependence
538 */
539 @Override
540 public boolean equals(Object ob) {
541 if (!(ob instanceof Exports))
542 return false;
543 Exports other = (Exports)ob;
544 return Objects.equals(this.mods, other.mods)
545 && Objects.equals(this.source, other.source)
546 && Objects.equals(this.targets, other.targets);
547 }
548
549 /**
550 * Returns a string describing the exported package.
551 *
552 * @return A string describing the exported package
553 */
554 @Override
555 public String toString() {
556 String s = ModuleDescriptor.toString(mods, source);
557 if (targets.isEmpty())
558 return s;
559 else
560 return s + " to " + targets;
561 }
562 }
563
564
565 /**
566 * <p> A package opened by a module, may be qualified or unqualified. </p>
567 *
568 * <p> The <em>opens</em> directive in a module declaration declares a
569 * package to be open to allow all types in the package, and all their
570 * members, not just public types and their public members to be reflected
571 * on by APIs that support private access or a way to bypass or suppress
572 * default Java language access control checks. </p>
573 *
574 * @see ModuleDescriptor#opens()
575 * @since 9
576 * @spec JPMS
577 */
578
579 public final static class Opens
580 implements Comparable<Opens>
581 {
582 /**
583 * A modifier on an open package.
584 *
585 * @see Opens#modifiers()
586 * @since 9
587 * @spec JPMS
588 */
589 public enum Modifier {
590
591 /**
592 * The open package was not explicitly or implicitly declared in
593 * the source of the module declaration.
594 */
595 SYNTHETIC,
596
597 /**
598 * The open package was implicitly declared in the source of the
599 * module declaration.
600 */
601 MANDATED;
602
603 }
604
605 private final Set<Modifier> mods;
606 private final String source;
607 private final Set<String> targets; // empty if unqualified export
608
609 /**
610 * Constructs an Opens
611 */
612 private Opens(Set<Modifier> ms, String source, Set<String> targets) {
613 this.mods = Set.copyOf(ms);
614 this.source = source;
615 this.targets = Set.copyOf(targets);
616 }
617
618 private Opens(Set<Modifier> ms,
619 String source,
620 Set<String> targets,
621 boolean unused) {
622 this.mods = ms;
623 this.source = source;
624 this.targets = targets;
625 }
626
627 /**
628 * Returns the set of modifiers.
629 *
630 * @return A possibly-empty unmodifiable set of modifiers
631 */
632 public Set<Modifier> modifiers() {
633 return mods;
634 }
635
636 /**
637 * Returns {@code true} if this is a qualified opens.
638 *
639 * @return {@code true} if this is a qualified opens
640 */
641 public boolean isQualified() {
642 return !targets.isEmpty();
643 }
644
645 /**
646 * Returns the package name.
647 *
648 * @return The package name
649 */
650 public String source() {
651 return source;
652 }
653
654 /**
655 * For a qualified opens, returns the non-empty and immutable set
656 * of the module names to which the package is open. For an
657 * unqualified opens, returns an empty set.
658 *
659 * @return The set of target module names or for an unqualified
660 * opens, an empty set
661 */
662 public Set<String> targets() {
663 return targets;
664 }
665
666 /**
667 * Compares this module opens to another.
668 *
669 * <p> Two {@code Opens} objects are compared by comparing the package
670 * names lexicographically. Where the packages names are equal then the
671 * sets of modifiers are compared in the same way that module modifiers
672 * are compared (see {@link ModuleDescriptor#compareTo
673 * ModuleDescriptor.compareTo}). Where the package names are equal and
674 * the set of modifiers are equal then the set of target modules are
675 * compared. This is done by sorting the names of the target modules
676 * in ascending order, and according to their natural ordering, and then
677 * comparing the corresponding elements lexicographically. Where the
678 * sets differ in size, and the larger set contains all elements of the
679 * smaller set, then the larger set is considered to succeed the smaller
680 * set. </p>
681 *
682 * @param that
683 * The module opens to compare
684 *
685 * @return A negative integer, zero, or a positive integer if this module
686 * opens is less than, equal to, or greater than the given
687 * module opens
688 */
689 @Override
690 public int compareTo(Opens that) {
691 if (this == that) return 0;
692
693 int c = source.compareTo(that.source);
694 if (c != 0)
695 return c;
696
697 // modifiers
698 long v1 = modsValue(this.modifiers());
699 long v2 = modsValue(that.modifiers());
700 c = Long.compare(v1, v2);
701 if (c != 0)
702 return c;
703
704 // targets
705 c = compare(targets, that.targets);
706 if (c != 0)
707 return c;
708
709 return 0;
710 }
711
712 /**
713 * Computes a hash code for this module opens.
714 *
715 * <p> The hash code is based upon the modifiers, the package name,
716 * and for a qualified opens, the set of modules names to which the
717 * package is opened. It satisfies the general contract of the
718 * {@link Object#hashCode Object.hashCode} method.
719 *
720 * @return The hash-code value for this module opens
721 */
722 @Override
723 public int hashCode() {
724 int hash = mods.hashCode();
725 hash = hash * 43 + source.hashCode();
726 return hash * 43 + targets.hashCode();
727 }
728
729 /**
730 * Tests this module opens for equality with the given object.
731 *
732 * <p> If the given object is not an {@code Opens} then this method
733 * returns {@code false}. Two {@code Opens} objects are equal if their
734 * set of modifiers is equal, the package names are equal and the set
735 * of target module names is equal. </p>
736 *
737 * <p> This method satisfies the general contract of the {@link
738 * java.lang.Object#equals(Object) Object.equals} method. </p>
739 *
740 * @param ob
741 * the object to which this object is to be compared
742 *
743 * @return {@code true} if, and only if, the given object is a module
744 * dependence that is equal to this module dependence
745 */
746 @Override
747 public boolean equals(Object ob) {
748 if (!(ob instanceof Opens))
749 return false;
750 Opens other = (Opens)ob;
751 return Objects.equals(this.mods, other.mods)
752 && Objects.equals(this.source, other.source)
753 && Objects.equals(this.targets, other.targets);
754 }
755
756 /**
757 * Returns a string describing the open package.
758 *
759 * @return A string describing the open package
760 */
761 @Override
762 public String toString() {
763 String s = ModuleDescriptor.toString(mods, source);
764 if (targets.isEmpty())
765 return s;
766 else
767 return s + " to " + targets;
768 }
769 }
770
771
772 /**
773 * <p> A service that a module provides one or more implementations of. </p>
774 *
775 * @see ModuleDescriptor#provides()
776 * @since 9
777 * @spec JPMS
778 */
779
780 public final static class Provides
781 implements Comparable<Provides>
782 {
783 private final String service;
784 private final List<String> providers;
785
786 private Provides(String service, List<String> providers) {
787 this.service = service;
788 this.providers = List.copyOf(providers);
789 }
790
791 private Provides(String service, List<String> providers, boolean unused) {
792 this.service = service;
793 this.providers = providers;
794 }
795
796 /**
797 * Returns the fully qualified class name of the service type.
798 *
799 * @return The fully qualified class name of the service type
800 */
801 public String service() { return service; }
802
803 /**
804 * Returns the list of the fully qualified class names of the providers
805 * or provider factories.
806 *
807 * @return A non-empty and unmodifiable list of the fully qualified class
808 * names of the providers or provider factories
809 */
810 public List<String> providers() { return providers; }
811
812 /**
813 * Compares this provides to another.
814 *
815 * <p> Two {@code Provides} objects are compared by comparing the fully
816 * qualified class name of the service type lexicographically. Where the
817 * class names are equal then the list of the provider class names are
818 * compared by comparing the corresponding elements of both lists
819 * lexicographically and in sequence. Where the lists differ in size,
820 * {@code N} is the size of the shorter list, and the first {@code N}
821 * corresponding elements are equal, then the longer list is considered
822 * to succeed the shorter list. </p>
823 *
824 * @param that
825 * The {@code Provides} to compare
826 *
827 * @return A negative integer, zero, or a positive integer if this provides
828 * is less than, equal to, or greater than the given provides
829 */
830 public int compareTo(Provides that) {
831 if (this == that) return 0;
832
833 int c = service.compareTo(that.service);
834 if (c != 0) return c;
835
836 // compare provider class names in sequence
837 int size1 = this.providers.size();
838 int size2 = that.providers.size();
839 for (int index=0; index<Math.min(size1, size2); index++) {
840 String e1 = this.providers.get(index);
841 String e2 = that.providers.get(index);
842 c = e1.compareTo(e2);
843 if (c != 0) return c;
844 }
845 if (size1 == size2) {
846 return 0;
847 } else {
848 return (size1 > size2) ? 1 : -1;
849 }
850 }
851
852 /**
853 * Computes a hash code for this provides.
854 *
855 * <p> The hash code is based upon the service type and the set of
856 * providers. It satisfies the general contract of the {@link
857 * Object#hashCode Object.hashCode} method. </p>
858 *
859 * @return The hash-code value for this module provides
860 */
861 @Override
862 public int hashCode() {
863 return service.hashCode() * 43 + providers.hashCode();
864 }
865
866 /**
867 * Tests this provides for equality with the given object.
868 *
869 * <p> If the given object is not a {@code Provides} then this method
870 * returns {@code false}. Two {@code Provides} objects are equal if the
871 * service type is equal and the list of providers is equal. </p>
872 *
873 * <p> This method satisfies the general contract of the {@link
874 * java.lang.Object#equals(Object) Object.equals} method. </p>
875 *
876 * @param ob
877 * the object to which this object is to be compared
878 *
879 * @return {@code true} if, and only if, the given object is a
880 * {@code Provides} that is equal to this {@code Provides}
881 */
882 @Override
883 public boolean equals(Object ob) {
884 if (!(ob instanceof Provides))
885 return false;
886 Provides other = (Provides)ob;
887 return Objects.equals(this.service, other.service) &&
888 Objects.equals(this.providers, other.providers);
889 }
890
891 /**
892 * Returns a string describing this provides.
893 *
894 * @return A string describing this provides
895 */
896 @Override
897 public String toString() {
898 return service + " with " + providers;
899 }
900
901 }
902
903
904
905 /**
906 * A module's version string.
907 *
908 * <p> A version string has three components: The version number itself, an
909 * optional pre-release version, and an optional build version. Each
910 * component is a sequence of tokens; each token is either a non-negative
911 * integer or a string. Tokens are separated by the punctuation characters
912 * {@code '.'}, {@code '-'}, or {@code '+'}, or by transitions from a
913 * sequence of digits to a sequence of characters that are neither digits
914 * nor punctuation characters, or vice versa.
915 *
916 * <ul>
917 *
918 * <li> The <i>version number</i> is a sequence of tokens separated by
919 * {@code '.'} characters, terminated by the first {@code '-'} or {@code
920 * '+'} character. </li>
921 *
922 * <li> The <i>pre-release version</i> is a sequence of tokens separated
923 * by {@code '.'} or {@code '-'} characters, terminated by the first
924 * {@code '+'} character. </li>
925 *
926 * <li> The <i>build version</i> is a sequence of tokens separated by
927 * {@code '.'}, {@code '-'}, or {@code '+'} characters.
928 *
929 * </ul>
930 *
931 * <p> When comparing two version strings, the elements of their
932 * corresponding components are compared in pointwise fashion. If one
933 * component is longer than the other, but otherwise equal to it, then the
934 * first component is considered the greater of the two; otherwise, if two
935 * corresponding elements are integers then they are compared as such;
936 * otherwise, at least one of the elements is a string, so the other is
937 * converted into a string if it is an integer and the two are compared
938 * lexicographically. Trailing integer elements with the value zero are
939 * ignored.
940 *
941 * <p> Given two version strings, if their version numbers differ then the
942 * result of comparing them is the result of comparing their version
943 * numbers; otherwise, if one of them has a pre-release version but the
944 * other does not then the first is considered to precede the second,
945 * otherwise the result of comparing them is the result of comparing their
946 * pre-release versions; otherwise, the result of comparing them is the
947 * result of comparing their build versions.
948 *
949 * @see ModuleDescriptor#version()
950 * @since 9
951 * @spec JPMS
952 */
953
954 public final static class Version
955 implements Comparable<Version>
956 {
957
958 private final String version;
959
960 // If Java had disjunctive types then we'd write List<Integer|String> here
961 //
962 private final List<Object> sequence;
963 private final List<Object> pre;
964 private final List<Object> build;
965
966 // Take a numeric token starting at position i
967 // Append it to the given list
968 // Return the index of the first character not taken
969 // Requires: s.charAt(i) is (decimal) numeric
970 //
971 private static int takeNumber(String s, int i, List<Object> acc) {
972 char c = s.charAt(i);
973 int d = (c - '0');
974 int n = s.length();
975 while (++i < n) {
976 c = s.charAt(i);
977 if (c >= '0' && c <= '9') {
978 d = d * 10 + (c - '0');
979 continue;
980 }
981 break;
982 }
983 acc.add(d);
984 return i;
985 }
986
987 // Take a string token starting at position i
988 // Append it to the given list
989 // Return the index of the first character not taken
990 // Requires: s.charAt(i) is not '.'
991 //
992 private static int takeString(String s, int i, List<Object> acc) {
993 int b = i;
994 int n = s.length();
995 while (++i < n) {
996 char c = s.charAt(i);
997 if (c != '.' && c != '-' && c != '+' && !(c >= '0' && c <= '9'))
998 continue;
999 break;
1000 }
1001 acc.add(s.substring(b, i));
1002 return i;
1003 }
1004
1005 // Syntax: tok+ ( '-' tok+)? ( '+' tok+)?
1006 // First token string is sequence, second is pre, third is build
1007 // Tokens are separated by '.' or '-', or by changes between alpha & numeric
1008 // Numeric tokens are compared as decimal integers
1009 // Non-numeric tokens are compared lexicographically
1010 // A version with a non-empty pre is less than a version with same seq but no pre
1011 // Tokens in build may contain '-' and '+'
1012 //
1013 private Version(String v) {
1014
1015 if (v == null)
1016 throw new IllegalArgumentException("Null version string");
1017 int n = v.length();
1018 if (n == 0)
1019 throw new IllegalArgumentException("Empty version string");
1020
1021 int i = 0;
1022 char c = v.charAt(i);
1023 if (!(c >= '0' && c <= '9'))
1024 throw new IllegalArgumentException(v
1025 + ": Version string does not start"
1026 + " with a number");
1027
1028 List<Object> sequence = new ArrayList<>(4);
1029 List<Object> pre = new ArrayList<>(2);
1030 List<Object> build = new ArrayList<>(2);
1031
1032 i = takeNumber(v, i, sequence);
1033
1034 while (i < n) {
1035 c = v.charAt(i);
1036 if (c == '.') {
1037 i++;
1038 continue;
1039 }
1040 if (c == '-' || c == '+') {
1041 i++;
1042 break;
1043 }
1044 if (c >= '0' && c <= '9')
1045 i = takeNumber(v, i, sequence);
1046 else
1047 i = takeString(v, i, sequence);
1048 }
1049
1050 if (c == '-' && i >= n)
1051 throw new IllegalArgumentException(v + ": Empty pre-release");
1052
1053 while (i < n) {
1054 c = v.charAt(i);
1055 if (c >= '0' && c <= '9')
1056 i = takeNumber(v, i, pre);
1057 else
1058 i = takeString(v, i, pre);
1059 if (i >= n)
1060 break;
1061 c = v.charAt(i);
1062 if (c == '.' || c == '-') {
1063 i++;
1064 continue;
1065 }
1066 if (c == '+') {
1067 i++;
1068 break;
1069 }
1070 }
1071
1072 if (c == '+' && i >= n)
1073 throw new IllegalArgumentException(v + ": Empty pre-release");
1074
1075 while (i < n) {
1076 c = v.charAt(i);
1077 if (c >= '0' && c <= '9')
1078 i = takeNumber(v, i, build);
1079 else
1080 i = takeString(v, i, build);
1081 if (i >= n)
1082 break;
1083 c = v.charAt(i);
1084 if (c == '.' || c == '-' || c == '+') {
1085 i++;
1086 continue;
1087 }
1088 }
1089
1090 this.version = v;
1091 this.sequence = sequence;
1092 this.pre = pre;
1093 this.build = build;
1094 }
1095
1096 /**
1097 * Parses the given string as a version string.
1098 *
1099 * @param v
1100 * The string to parse
1101 *
1102 * @return The resulting {@code Version}
1103 *
1104 * @throws IllegalArgumentException
1105 * If {@code v} is {@code null}, an empty string, or cannot be
1106 * parsed as a version string
1107 */
1108 public static Version parse(String v) {
1109 return new Version(v);
1110 }
1111
1112 @SuppressWarnings("unchecked")
1113 private int cmp(Object o1, Object o2) {
1114 return ((Comparable)o1).compareTo(o2);
1115 }
1116
1117 private int compareTokens(List<Object> ts1, List<Object> ts2) {
1118 int n = Math.min(ts1.size(), ts2.size());
1119 for (int i = 0; i < n; i++) {
1120 Object o1 = ts1.get(i);
1121 Object o2 = ts2.get(i);
1122 if ((o1 instanceof Integer && o2 instanceof Integer)
1123 || (o1 instanceof String && o2 instanceof String))
1124 {
1125 int c = cmp(o1, o2);
1126 if (c == 0)
1127 continue;
1128 return c;
1129 }
1130 // Types differ, so convert number to string form
1131 int c = o1.toString().compareTo(o2.toString());
1132 if (c == 0)
1133 continue;
1134 return c;
1135 }
1136 List<Object> rest = ts1.size() > ts2.size() ? ts1 : ts2;
1137 int e = rest.size();
1138 for (int i = n; i < e; i++) {
1139 Object o = rest.get(i);
1140 if (o instanceof Integer && ((Integer)o) == 0)
1141 continue;
1142 return ts1.size() - ts2.size();
1143 }
1144 return 0;
1145 }
1146
1147 /**
1148 * Compares this module version to another module version. Module
1149 * versions are compared as described in the class description.
1150 *
1151 * @param that
1152 * The module version to compare
1153 *
1154 * @return A negative integer, zero, or a positive integer as this
1155 * module version is less than, equal to, or greater than the
1156 * given module version
1157 */
1158 @Override
1159 public int compareTo(Version that) {
1160 int c = compareTokens(this.sequence, that.sequence);
1161 if (c != 0) return c;
1162 if (this.pre.isEmpty()) {
1163 if (!that.pre.isEmpty()) return +1;
1164 } else {
1165 if (that.pre.isEmpty()) return -1;
1166 }
1167 c = compareTokens(this.pre, that.pre);
1168 if (c != 0) return c;
1169 return compareTokens(this.build, that.build);
1170 }
1171
1172 /**
1173 * Tests this module version for equality with the given object.
1174 *
1175 * <p> If the given object is not a {@code Version} then this method
1176 * returns {@code false}. Two module version are equal if their
1177 * corresponding components are equal. </p>
1178 *
1179 * <p> This method satisfies the general contract of the {@link
1180 * java.lang.Object#equals(Object) Object.equals} method. </p>
1181 *
1182 * @param ob
1183 * the object to which this object is to be compared
1184 *
1185 * @return {@code true} if, and only if, the given object is a module
1186 * reference that is equal to this module reference
1187 */
1188 @Override
1189 public boolean equals(Object ob) {
1190 if (!(ob instanceof Version))
1191 return false;
1192 return compareTo((Version)ob) == 0;
1193 }
1194
1195 /**
1196 * Computes a hash code for this module version.
1197 *
1198 * <p> The hash code is based upon the components of the version and
1199 * satisfies the general contract of the {@link Object#hashCode
1200 * Object.hashCode} method. </p>
1201 *
1202 * @return The hash-code value for this module version
1203 */
1204 @Override
1205 public int hashCode() {
1206 return version.hashCode();
1207 }
1208
1209 /**
1210 * Returns the string from which this version was parsed.
1211 *
1212 * @return The string from which this version was parsed.
1213 */
1214 @Override
1215 public String toString() {
1216 return version;
1217 }
1218
1219 }
1220
1221
1222 private final String name;
1223 private final Version version;
1224 private final String rawVersionString;
1225 private final Set<Modifier> modifiers;
1226 private final boolean open; // true if modifiers contains OPEN
1227 private final boolean automatic; // true if modifiers contains AUTOMATIC
1228 private final Set<Requires> requires;
1229 private final Set<Exports> exports;
1230 private final Set<Opens> opens;
1231 private final Set<String> uses;
1232 private final Set<Provides> provides;
1233 private final Set<String> packages;
1234 private final String mainClass;
1235
1236 private ModuleDescriptor(String name,
1237 Version version,
1238 String rawVersionString,
1239 Set<Modifier> modifiers,
1240 Set<Requires> requires,
1241 Set<Exports> exports,
1242 Set<Opens> opens,
1243 Set<String> uses,
1244 Set<Provides> provides,
1245 Set<String> packages,
1246 String mainClass)
1247 {
1248 assert version == null || rawVersionString == null;
1249 this.name = name;
1250 this.version = version;
1251 this.rawVersionString = rawVersionString;
1252 this.modifiers = Set.copyOf(modifiers);
1253 this.open = modifiers.contains(Modifier.OPEN);
1254 this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1255 assert (requires.stream().map(Requires::name).distinct().count()
1256 == requires.size());
1257 this.requires = Set.copyOf(requires);
1258 this.exports = Set.copyOf(exports);
1259 this.opens = Set.copyOf(opens);
1260 this.uses = Set.copyOf(uses);
1261 this.provides = Set.copyOf(provides);
1262
1263 this.packages = Set.copyOf(packages);
1264 this.mainClass = mainClass;
1265 }
1266
1267 /**
1268 * Creates a module descriptor from its components.
1269 * The arguments are pre-validated and sets are unmodifiable sets.
1270 */
1271 ModuleDescriptor(String name,
1272 Version version,
1273 Set<Modifier> modifiers,
1274 Set<Requires> requires,
1275 Set<Exports> exports,
1276 Set<Opens> opens,
1277 Set<String> uses,
1278 Set<Provides> provides,
1279 Set<String> packages,
1280 String mainClass,
1281 int hashCode,
1282 boolean unused) {
1283 this.name = name;
1284 this.version = version;
1285 this.rawVersionString = null;
1286 this.modifiers = modifiers;
1287 this.open = modifiers.contains(Modifier.OPEN);
1288 this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1289 this.requires = requires;
1290 this.exports = exports;
1291 this.opens = opens;
1292 this.uses = uses;
1293 this.provides = provides;
1294 this.packages = packages;
1295 this.mainClass = mainClass;
1296 this.hash = hashCode;
1297 }
1298
1299 /**
1300 * <p> Returns the module name. </p>
1301 *
1302 * @return The module name
1303 */
1304 public String name() {
1305 return name;
1306 }
1307
1308 /**
1309 * <p> Returns the set of module modifiers. </p>
1310 *
1311 * @return A possibly-empty unmodifiable set of modifiers
1312 */
1313 public Set<Modifier> modifiers() {
1314 return modifiers;
1315 }
1316
1317 /**
1318 * <p> Returns {@code true} if this is an open module. </p>
1319 *
1320 * <p> This method is equivalent to testing if the set of {@link #modifiers()
1321 * modifiers} contains the {@link Modifier#OPEN OPEN} modifier. </p>
1322 *
1323 * @return {@code true} if this is an open module
1324 */
1325 public boolean isOpen() {
1326 return open;
1327 }
1328
1329 /**
1330 * <p> Returns {@code true} if this is an automatic module. </p>
1331 *
1332 * <p> This method is equivalent to testing if the set of {@link #modifiers()
1333 * modifiers} contains the {@link Modifier#OPEN AUTOMATIC} modifier. </p>
1334 *
1335 * @return {@code true} if this is an automatic module
1336 */
1337 public boolean isAutomatic() {
1338 return automatic;
1339 }
1340
1341 /**
1342 * <p> Returns the set of {@code Requires} objects representing the module
1343 * dependences. </p>
1344 *
1345 * <p> The set includes a dependency on "{@code java.base}" when this
1346 * module is not named "{@code java.base}". If this module is an automatic
1347 * module then it does not have a dependency on any module other than
1348 * "{@code java.base}". </p>
1349 *
1350 * @return A possibly-empty unmodifiable set of {@link Requires} objects
1351 */
1352 public Set<Requires> requires() {
1353 return requires;
1354 }
1355
1356 /**
1357 * <p> Returns the set of {@code Exports} objects representing the exported
1358 * packages. </p>
1359 *
1360 * <p> If this module is an automatic module then the set of exports
1361 * is empty. </p>
1362 *
1363 * @return A possibly-empty unmodifiable set of exported packages
1364 */
1365 public Set<Exports> exports() {
1366 return exports;
1367 }
1368
1369 /**
1370 * <p> Returns the set of {@code Opens} objects representing the open
1371 * packages. </p>
1372 *
1373 * <p> If this module is an open module or an automatic module then the
1374 * set of open packages is empty. </p>
1375 *
1376 * @return A possibly-empty unmodifiable set of open packages
1377 */
1378 public Set<Opens> opens() {
1379 return opens;
1380 }
1381
1382 /**
1383 * <p> Returns the set of service dependences. </p>
1384 *
1385 * <p> If this module is an automatic module then the set of service
1386 * dependences is empty. </p>
1387 *
1388 * @return A possibly-empty unmodifiable set of the fully qualified class
1389 * names of the service types used
1390 */
1391 public Set<String> uses() {
1392 return uses;
1393 }
1394
1395 /**
1396 * <p> Returns the set of {@code Provides} objects representing the
1397 * services that the module provides. </p>
1398 *
1399 * @return The possibly-empty unmodifiable set of the services that this
1400 * module provides
1401 */
1402 public Set<Provides> provides() {
1403 return provides;
1404 }
1405
1406 /**
1407 * <p> Returns the module version. </p>
1408 *
1409 * @return This module's version, or an empty {@code Optional} if the
1410 * module does not have a version or the version is
1411 * {@linkplain Version#parse(String) unparseable}
1412 */
1413 public Optional<Version> version() {
1414 return Optional.ofNullable(version);
1415 }
1416
1417 /**
1418 * <p> Returns the string with the possibly-unparseable version of the
1419 * module </p>
1420 *
1421 * @return The string containing the version of the module or an empty
1422 * {@code Optional} if the module does not have a version
1423 *
1424 * @see #version()
1425 */
1426 public Optional<String> rawVersion() {
1427 if (version != null) {
1428 return Optional.of(version.toString());
1429 } else {
1430 return Optional.ofNullable(rawVersionString);
1431 }
1432 }
1433
1434 /**
1435 * <p> Returns a string containing the module name and, if present, its
1436 * version. </p>
1437 *
1438 * @return A string containing the module name and, if present, its
1439 * version
1440 */
1441 public String toNameAndVersion() {
1442 if (version != null) {
1443 return name() + "@" + version;
1444 } else {
1445 return name();
1446 }
1447 }
1448
1449 /**
1450 * <p> Returns the module main class. </p>
1451 *
1452 * @return The fully qualified class name of the module's main class
1453 */
1454 public Optional<String> mainClass() {
1455 return Optional.ofNullable(mainClass);
1456 }
1457
1458 /**
1459 * Returns the set of packages in the module.
1460 *
1461 * <p> The set of packages includes all exported and open packages, as well
1462 * as the packages of any service providers, and the package for the main
1463 * class. </p>
1464 *
1465 * @return A possibly-empty unmodifiable set of the packages in the module
1466 */
1467 public Set<String> packages() {
1468 return packages;
1469 }
1470
1471
1472 /**
1473 * A builder for building {@link ModuleDescriptor} objects.
1474 *
1475 * <p> {@code ModuleDescriptor} defines the {@link #newModule newModule},
1476 * {@link #newOpenModule newOpenModule}, and {@link #newAutomaticModule
1477 * newAutomaticModule} methods to create builders for building
1478 * <em>normal</em>, open, and automatic modules. </p>
1479 *
1480 * <p> The set of packages in the module are accumulated by the {@code
1481 * Builder} as the {@link ModuleDescriptor.Builder#exports(String) exports},
1482 * {@link ModuleDescriptor.Builder#opens(String) opens},
1483 * {@link ModuleDescriptor.Builder#packages(Set) packages},
1484 * {@link ModuleDescriptor.Builder#provides(String,List) provides}, and
1485 * {@link ModuleDescriptor.Builder#mainClass(String) mainClass} methods are
1486 * invoked. </p>
1487 *
1488 * <p> The module names, package names, and class names that are parameters
1489 * specified to the builder methods are the module names, package names,
1490 * and qualified names of classes (in named packages) as defined in the
1491 * <cite>The Java™ Language Specification</cite>. </p>
1492 *
1493 * <p> Example usage: </p>
1494 * <pre>{@code ModuleDescriptor descriptor = ModuleDescriptor.newModule("stats.core")
1495 * .requires("java.base")
1496 * .exports("org.acme.stats.core.clustering")
1497 * .exports("org.acme.stats.core.regression")
1498 * .packages(Set.of("org.acme.stats.core.internal"))
1499 * .build();
1500 * }</pre>
1501 *
1502 * @apiNote A {@code Builder} checks the components and invariants as
1503 * components are added to the builder. The rationale for this is to detect
1504 * errors as early as possible and not defer all validation to the
1505 * {@link #build build} method.
1506 *
1507 * @since 9
1508 * @spec JPMS
1509 */
1510 public static final class Builder {
1511 final String name;
1512 final boolean strict;
1513 final Set<Modifier> modifiers;
1514 final boolean open;
1515 final boolean automatic;
1516 final Set<String> packages = new HashSet<>();
1517 final Map<String, Requires> requires = new HashMap<>();
1518 final Map<String, Exports> exports = new HashMap<>();
1519 final Map<String, Opens> opens = new HashMap<>();
1520 final Set<String> uses = new HashSet<>();
1521 final Map<String, Provides> provides = new HashMap<>();
1522 Version version;
1523 String rawVersionString;
1524 String mainClass;
1525
1526 /**
1527 * Initializes a new builder with the given module name.
1528 *
1529 * If {@code strict} is {@code true} then module, package, and class
1530 * names are checked to ensure they are legal names. In addition, the
1531 * {@link #build buid} method will add "{@code requires java.base}" if
1532 * the dependency is not declared.
1533 */
1534 Builder(String name, boolean strict, Set<Modifier> modifiers) {
1535 this.name = (strict) ? requireModuleName(name) : name;
1536 this.strict = strict;
1537 this.modifiers = modifiers;
1538 this.open = modifiers.contains(Modifier.OPEN);
1539 this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1540 assert !open || !automatic;
1541 }
1542
1543 /**
1544 * Returns a snapshot of the packages in the module.
1545 */
1546 /* package */ Set<String> packages() {
1547 return Collections.unmodifiableSet(packages);
1548 }
1549
1550 /**
1551 * Adds a dependence on a module.
1552 *
1553 * @param req
1554 * The dependence
1555 *
1556 * @return This builder
1557 *
1558 * @throws IllegalArgumentException
1559 * If the dependence is on the module that this builder was
1560 * initialized to build
1561 * @throws IllegalStateException
1562 * If the dependence on the module has already been declared
1563 * or this builder is for an automatic module
1564 */
1565 public Builder requires(Requires req) {
1566 if (automatic)
1567 throw new IllegalStateException("Automatic modules cannot declare"
1568 + " dependences");
1569 String mn = req.name();
1570 if (name.equals(mn))
1571 throw new IllegalArgumentException("Dependence on self");
1572 if (requires.containsKey(mn))
1573 throw new IllegalStateException("Dependence upon " + mn
1574 + " already declared");
1575 requires.put(mn, req);
1576 return this;
1577 }
1578
1579 /**
1580 * Adds a dependence on a module with the given (and possibly empty)
1581 * set of modifiers. The dependence includes the version of the
1582 * module that was recorded at compile-time.
1583 *
1584 * @param ms
1585 * The set of modifiers
1586 * @param mn
1587 * The module name
1588 * @param compiledVersion
1589 * The version of the module recorded at compile-time
1590 *
1591 * @return This builder
1592 *
1593 * @throws IllegalArgumentException
1594 * If the module name is {@code null}, is not a legal module
1595 * name, or is equal to the module name that this builder
1596 * was initialized to build
1597 * @throws IllegalStateException
1598 * If the dependence on the module has already been declared
1599 * or this builder is for an automatic module
1600 */
1601 public Builder requires(Set<Requires.Modifier> ms,
1602 String mn,
1603 Version compiledVersion) {
1604 Objects.requireNonNull(compiledVersion);
1605 if (strict)
1606 mn = requireModuleName(mn);
1607 return requires(new Requires(ms, mn, compiledVersion, null));
1608 }
1609
1610 /* package */Builder requires(Set<Requires.Modifier> ms,
1611 String mn,
1612 String rawCompiledVersion) {
1613 Requires r;
1614 try {
1615 Version v = Version.parse(rawCompiledVersion);
1616 r = new Requires(ms, mn, v, null);
1617 } catch (IllegalArgumentException e) {
1618 if (strict) throw e;
1619 r = new Requires(ms, mn, null, rawCompiledVersion);
1620 }
1621 return requires(r);
1622 }
1623
1624 /**
1625 * Adds a dependence on a module with the given (and possibly empty)
1626 * set of modifiers.
1627 *
1628 * @param ms
1629 * The set of modifiers
1630 * @param mn
1631 * The module name
1632 *
1633 * @return This builder
1634 *
1635 * @throws IllegalArgumentException
1636 * If the module name is {@code null}, is not a legal module
1637 * name, or is equal to the module name that this builder
1638 * was initialized to build
1639 * @throws IllegalStateException
1640 * If the dependence on the module has already been declared
1641 * or this builder is for an automatic module
1642 */
1643 public Builder requires(Set<Requires.Modifier> ms, String mn) {
1644 if (strict)
1645 mn = requireModuleName(mn);
1646 return requires(new Requires(ms, mn, null, null));
1647 }
1648
1649 /**
1650 * Adds a dependence on a module with an empty set of modifiers.
1651 *
1652 * @param mn
1653 * The module name
1654 *
1655 * @return This builder
1656 *
1657 * @throws IllegalArgumentException
1658 * If the module name is {@code null}, is not a legal module
1659 * name, or is equal to the module name that this builder
1660 * was initialized to build
1661 * @throws IllegalStateException
1662 * If the dependence on the module has already been declared
1663 * or this builder is for an automatic module
1664 */
1665 public Builder requires(String mn) {
1666 return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
1667 }
1668
1669 /**
1670 * Adds an exported package.
1671 *
1672 * @param e
1673 * The export
1674 *
1675 * @return This builder
1676 *
1677 * @throws IllegalStateException
1678 * If the {@link Exports#source() package} is already declared as
1679 * exported or this builder is for an automatic module
1680 */
1681 public Builder exports(Exports e) {
1682 if (automatic) {
1683 throw new IllegalStateException("Automatic modules cannot declare"
1684 + " exported packages");
1685 }
1686 String source = e.source();
1687 if (exports.containsKey(source)) {
1688 throw new IllegalStateException("Exported package " + source
1689 + " already declared");
1690 }
1691 exports.put(source, e);
1692 packages.add(source);
1693 return this;
1694 }
1695
1696 /**
1697 * Adds an exported package with the given (and possibly empty) set of
1698 * modifiers. The package is exported to a set of target modules.
1699 *
1700 * @param ms
1701 * The set of modifiers
1702 * @param pn
1703 * The package name
1704 * @param targets
1705 * The set of target modules names
1706 *
1707 * @return This builder
1708 *
1709 * @throws IllegalArgumentException
1710 * If the package name is {@code null} or is not a legal
1711 * package name, the set of target modules is empty, or the set
1712 * of target modules contains a name that is not a legal module
1713 * name
1714 * @throws IllegalStateException
1715 * If the package is already declared as exported
1716 * or this builder is for an automatic module
1717 */
1718 public Builder exports(Set<Exports.Modifier> ms,
1719 String pn,
1720 Set<String> targets)
1721 {
1722 targets = new HashSet<>(targets);
1723 if (targets.isEmpty())
1724 throw new IllegalArgumentException("Empty target set");
1725 if (strict) {
1726 requirePackageName(pn);
1727 targets.forEach(Checks::requireModuleName);
1728 }
1729 Exports e = new Exports(ms, pn, targets);
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, Set.of());
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(Set.of(), 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(Set.of(), 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 targets = new HashSet<>(targets);
1857 if (targets.isEmpty())
1858 throw new IllegalArgumentException("Empty target set");
1859 if (strict) {
1860 requirePackageName(pn);
1861 targets.forEach(Checks::requireModuleName);
1862 }
1863 Opens opens = new Opens(ms, pn, targets);
1864 return opens(opens);
1865 }
1866
1867 /**
1868 * Adds an open package with the given (and possibly empty) set of
1869 * modifiers. The package is open to all modules.
1870 *
1871 * @param ms
1872 * The set of modifiers
1873 * @param pn
1874 * The package name
1875 *
1876 * @return This builder
1877 *
1878 * @throws IllegalArgumentException
1879 * If the package name is {@code null} or is not a legal
1880 * package name
1881 * @throws IllegalStateException
1882 * If the package is already declared as open, or this is a
1883 * builder for an open module or automatic module
1884 */
1885 public Builder opens(Set<Opens.Modifier> ms, String pn) {
1886 if (strict) {
1887 requirePackageName(pn);
1888 }
1889 Opens e = new Opens(ms, pn, Set.of());
1890 return opens(e);
1891 }
1892
1893 /**
1894 * Adds an open package. The package is open to a set of target modules.
1895 *
1896 * @param pn
1897 * The package name
1898 * @param targets
1899 * The set of target modules names
1900 *
1901 * @return This builder
1902 *
1903 * @throws IllegalArgumentException
1904 * If the package name is {@code null} or is not a legal
1905 * package name, the set of target modules is empty, or the set
1906 * of target modules contains a name that is not a legal module
1907 * name
1908 * @throws IllegalStateException
1909 * If the package is already declared as open, or this is a
1910 * builder for an open module or automatic module
1911 */
1912 public Builder opens(String pn, Set<String> targets) {
1913 return opens(Set.of(), pn, targets);
1914 }
1915
1916 /**
1917 * Adds an open package. The package is open to all modules.
1918 *
1919 * @param pn
1920 * The package name
1921 *
1922 * @return This builder
1923 *
1924 * @throws IllegalArgumentException
1925 * If the package name is {@code null} or is not a legal
1926 * package name
1927 * @throws IllegalStateException
1928 * If the package is already declared as open, or this is a
1929 * builder for an open module or automatic module
1930 */
1931 public Builder opens(String pn) {
1932 return opens(Set.of(), pn);
1933 }
1934
1935 /**
1936 * Adds a service dependence.
1937 *
1938 * @param service
1939 * The service type
1940 *
1941 * @return This builder
1942 *
1943 * @throws IllegalArgumentException
1944 * If the service type is {@code null} or not a qualified name of
1945 * a class in a named package
1946 * @throws IllegalStateException
1947 * If a dependency on the service type has already been declared
1948 * or this is a builder for an automatic module
1949 */
1950 public Builder uses(String service) {
1951 if (automatic)
1952 throw new IllegalStateException("Automatic modules can not declare"
1953 + " service dependences");
1954 if (uses.contains(requireServiceTypeName(service)))
1955 throw new IllegalStateException("Dependence upon service "
1956 + service + " already declared");
1957 uses.add(service);
1958 return this;
1959 }
1960
1961 /**
1962 * Provides a service with one or more implementations. The package for
1963 * each {@link Provides#providers provider} (or provider factory) is
1964 * added to the module if not already added.
1965 *
1966 * @param p
1967 * The provides
1968 *
1969 * @return This builder
1970 *
1971 * @throws IllegalStateException
1972 * If the providers for the service type have already been
1973 * declared
1974 */
1975 public Builder provides(Provides p) {
1976 String service = p.service();
1977 if (provides.containsKey(service))
1978 throw new IllegalStateException("Providers of service "
1979 + service + " already declared");
1980 provides.put(service, p);
1981 p.providers().forEach(name -> packages.add(packageName(name)));
1982 return this;
1983 }
1984
1985 /**
1986 * Provides implementations of a service. The package for each provider
1987 * (or provider factory) is added to the module if not already added.
1988 *
1989 * @param service
1990 * The service type
1991 * @param providers
1992 * The list of provider or provider factory class names
1993 *
1994 * @return This builder
1995 *
1996 * @throws IllegalArgumentException
1997 * If the service type or any of the provider class names is
1998 * {@code null} or not a qualified name of a class in a named
1999 * package, or the list of provider class names is empty
2000 * @throws IllegalStateException
2001 * If the providers for the service type have already been
2002 * declared
2003 */
2004 public Builder provides(String service, List<String> providers) {
2005 providers = new ArrayList<>(providers);
2006 if (providers.isEmpty())
2007 throw new IllegalArgumentException("Empty providers set");
2008 if (strict) {
2009 requireServiceTypeName(service);
2010 providers.forEach(Checks::requireServiceProviderName);
2011 } else {
2012 // Disallow service/providers in unnamed package
2013 String pn = packageName(service);
2014 if (pn.isEmpty()) {
2015 throw new IllegalArgumentException(service
2016 + ": unnamed package");
2017 }
2018 for (String name : providers) {
2019 pn = packageName(name);
2020 if (pn.isEmpty()) {
2021 throw new IllegalArgumentException(name
2022 + ": unnamed package");
2023 }
2024 }
2025 }
2026 Provides p = new Provides(service, providers);
2027 return provides(p);
2028 }
2029
2030 /**
2031 * Adds packages to the module. All packages in the set of package names
2032 * that are not in the module are added to module.
2033 *
2034 * @param pns
2035 * The (possibly empty) set of package names
2036 *
2037 * @return This builder
2038 *
2039 * @throws IllegalArgumentException
2040 * If any of the package names is {@code null} or is not a
2041 * legal package name
2042 */
2043 public Builder packages(Set<String> pns) {
2044 if (strict) {
2045 pns = new HashSet<>(pns);
2046 pns.forEach(Checks::requirePackageName);
2047 }
2048 this.packages.addAll(pns);
2049 return this;
2050 }
2051
2052 /**
2053 * Sets the module version.
2054 *
2055 * @param v
2056 * The version
2057 *
2058 * @return This builder
2059 */
2060 public Builder version(Version v) {
2061 version = requireNonNull(v);
2062 rawVersionString = null;
2063 return this;
2064 }
2065
2066 /**
2067 * Sets the module version.
2068 *
2069 * @param vs
2070 * The version string to parse
2071 *
2072 * @return This builder
2073 *
2074 * @throws IllegalArgumentException
2075 * If {@code vs} is {@code null} or cannot be parsed as a
2076 * version string
2077 *
2078 * @see Version#parse(String)
2079 */
2080 public Builder version(String vs) {
2081 try {
2082 version = Version.parse(vs);
2083 rawVersionString = null;
2084 } catch (IllegalArgumentException e) {
2085 if (strict) throw e;
2086 version = null;
2087 rawVersionString = vs;
2088 }
2089 return this;
2090 }
2091
2092 /**
2093 * Sets the module main class. The package for the main class is added
2094 * to the module if not already added. In other words, this method is
2095 * equivalent to first invoking this builder's {@link #packages(Set)
2096 * packages} method to add the package name of the main class.
2097 *
2098 * @param mc
2099 * The module main class
2100 *
2101 * @return This builder
2102 *
2103 * @throws IllegalArgumentException
2104 * If {@code mainClass} is {@code null} or not a qualified
2105 * name of a class in a named package
2106 */
2107 public Builder mainClass(String mc) {
2108 String pn;
2109 if (strict) {
2110 mc = requireQualifiedClassName("main class name", mc);
2111 pn = packageName(mc);
2112 assert !pn.isEmpty();
2113 } else {
2114 // Disallow main class in unnamed package
2115 pn = packageName(mc);
2116 if (pn.isEmpty()) {
2117 throw new IllegalArgumentException(mc + ": unnamed package");
2118 }
2119 }
2120 packages.add(pn);
2121 mainClass = mc;
2122 return this;
2123 }
2124
2125 /**
2126 * Builds and returns a {@code ModuleDescriptor} from its components.
2127 *
2128 * <p> The module will require "{@code java.base}" even if the dependence
2129 * has not been declared (the exception is when building a module named
2130 * "{@code java.base}" as it cannot require itself). The dependence on
2131 * "{@code java.base}" will have the {@link
2132 * java.lang.module.ModuleDescriptor.Requires.Modifier#MANDATED MANDATED}
2133 * modifier if the dependence was not declared. </p>
2134 *
2135 * @return The module descriptor
2136 */
2137 public ModuleDescriptor build() {
2138 Set<Requires> requires = new HashSet<>(this.requires.values());
2139 Set<Exports> exports = new HashSet<>(this.exports.values());
2140 Set<Opens> opens = new HashSet<>(this.opens.values());
2141
2142 // add dependency on java.base
2143 if (strict
2144 && !name.equals("java.base")
2145 && !this.requires.containsKey("java.base")) {
2146 requires.add(new Requires(Set.of(Requires.Modifier.MANDATED),
2147 "java.base",
2148 null,
2149 null));
2150 }
2151
2152 Set<Provides> provides = new HashSet<>(this.provides.values());
2153
2154 return new ModuleDescriptor(name,
2155 version,
2156 rawVersionString,
2157 modifiers,
2158 requires,
2159 exports,
2160 opens,
2161 uses,
2162 provides,
2163 packages,
2164 mainClass);
2165 }
2166
2167 }
2168
2169 /**
2170 * Compares this module descriptor to another.
2171 *
2172 * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
2173 * module names lexicographically. Where the module names are equal then the
2174 * module versions are compared. When comparing the module versions then a
2175 * module descriptor with a version is considered to succeed a module
2176 * descriptor that does not have a version. If both versions are {@linkplain
2177 * Version#parse(String) unparseable} then the {@linkplain #rawVersion()
2178 * raw version strings} are compared lexicographically. Where the module names
2179 * are equal and the versions are equal (or not present in both), then the
2180 * set of modifiers are compared. Sets of modifiers are compared by comparing
2181 * a <em>binary value</em> computed for each set. If a modifier is present
2182 * in the set then the bit at the position of its ordinal is {@code 1}
2183 * in the binary value, otherwise {@code 0}. If the two set of modifiers
2184 * are also equal then the other components of the module descriptors are
2185 * compared in a manner that is consistent with {@code equals}. </p>
2186 *
2187 * @param that
2188 * The module descriptor to compare
2189 *
2190 * @return A negative integer, zero, or a positive integer if this module
2191 * descriptor is less than, equal to, or greater than the given
2192 * module descriptor
2193 */
2194 @Override
2195 public int compareTo(ModuleDescriptor that) {
2196 if (this == that) return 0;
2197
2198 int c = this.name().compareTo(that.name());
2199 if (c != 0) return c;
2200
2201 c = compare(this.version, that.version);
2202 if (c != 0) return c;
2203
2204 c = compare(this.rawVersionString, that.rawVersionString);
2205 if (c != 0) return c;
2206
2207 long v1 = modsValue(this.modifiers());
2208 long v2 = modsValue(that.modifiers());
2209 c = Long.compare(v1, v2);
2210 if (c != 0) return c;
2211
2212 c = compare(this.requires, that.requires);
2213 if (c != 0) return c;
2214
2215 c = compare(this.packages, that.packages);
2216 if (c != 0) return c;
2217
2218 c = compare(this.exports, that.exports);
2219 if (c != 0) return c;
2220
2221 c = compare(this.opens, that.opens);
2222 if (c != 0) return c;
2223
2224 c = compare(this.uses, that.uses);
2225 if (c != 0) return c;
2226
2227 c = compare(this.provides, that.provides);
2228 if (c != 0) return c;
2229
2230 c = compare(this.mainClass, that.mainClass);
2231 if (c != 0) return c;
2232
2233 return 0;
2234 }
2235
2236 /**
2237 * Tests this module descriptor for equality with the given object.
2238 *
2239 * <p> If the given object is not a {@code ModuleDescriptor} then this
2240 * method returns {@code false}. Two module descriptors are equal if each
2241 * of their corresponding components is equal. </p>
2242 *
2243 * <p> This method satisfies the general contract of the {@link
2244 * java.lang.Object#equals(Object) Object.equals} method. </p>
2245 *
2246 * @param ob
2247 * the object to which this object is to be compared
2248 *
2249 * @return {@code true} if, and only if, the given object is a module
2250 * descriptor that is equal to this module descriptor
2251 */
2252 @Override
2253 public boolean equals(Object ob) {
2254 if (ob == this)
2255 return true;
2256 if (!(ob instanceof ModuleDescriptor))
2257 return false;
2258 ModuleDescriptor that = (ModuleDescriptor)ob;
2259 return (name.equals(that.name)
2260 && modifiers.equals(that.modifiers)
2261 && requires.equals(that.requires)
2262 && Objects.equals(packages, that.packages)
2263 && exports.equals(that.exports)
2264 && opens.equals(that.opens)
2265 && uses.equals(that.uses)
2266 && provides.equals(that.provides)
2267 && Objects.equals(version, that.version)
2268 && Objects.equals(rawVersionString, that.rawVersionString)
2269 && Objects.equals(mainClass, that.mainClass));
2270 }
2271
2272 /**
2273 * Computes a hash code for this module descriptor.
2274 *
2275 * <p> The hash code is based upon the components of the module descriptor,
2276 * and satisfies the general contract of the {@link Object#hashCode
2277 * Object.hashCode} method. </p>
2278 *
2279 * @return The hash-code value for this module descriptor
2280 */
2281 @Override
2282 public int hashCode() {
2283 int hc = hash;
2284 if (hc == 0) {
2285 hc = name.hashCode();
2286 hc = hc * 43 + Objects.hashCode(modifiers);
2287 hc = hc * 43 + requires.hashCode();
2288 hc = hc * 43 + Objects.hashCode(packages);
2289 hc = hc * 43 + exports.hashCode();
2290 hc = hc * 43 + opens.hashCode();
2291 hc = hc * 43 + uses.hashCode();
2292 hc = hc * 43 + provides.hashCode();
2293 hc = hc * 43 + Objects.hashCode(version);
2294 hc = hc * 43 + Objects.hashCode(rawVersionString);
2295 hc = hc * 43 + Objects.hashCode(mainClass);
2296 if (hc == 0)
2297 hc = -1;
2298 hash = hc;
2299 }
2300 return hc;
2301 }
2302 private transient int hash; // cached hash code
2303
2304 /**
2305 * <p> Returns a string describing the module. </p>
2306 *
2307 * @return A string describing the module
2308 */
2309 @Override
2310 public String toString() {
2311 StringBuilder sb = new StringBuilder();
2312
2313 if (isOpen())
2314 sb.append("open ");
2315 sb.append("module { name: ").append(toNameAndVersion());
2316 if (!requires.isEmpty())
2317 sb.append(", ").append(requires);
2318 if (!uses.isEmpty())
2319 sb.append(", uses: ").append(uses);
2320 if (!exports.isEmpty())
2321 sb.append(", exports: ").append(exports);
2322 if (!opens.isEmpty())
2323 sb.append(", opens: ").append(opens);
2324 if (!provides.isEmpty()) {
2325 sb.append(", provides: ").append(provides);
2326 }
2327 sb.append(" }");
2328 return sb.toString();
2329 }
2330
2331
2332 /**
2333 * Instantiates a builder to build a module descriptor.
2334 *
2335 * @param name
2336 * The module name
2337 * @param ms
2338 * The set of module modifiers
2339 *
2340 * @return A new builder
2341 *
2342 * @throws IllegalArgumentException
2343 * If the module name is {@code null} or is not a legal module
2344 * name, or the set of modifiers contains {@link
2345 * Modifier#AUTOMATIC AUTOMATIC} with other modifiers
2346 */
2347 public static Builder newModule(String name, Set<Modifier> ms) {
2348 Set<Modifier> mods = new HashSet<>(ms);
2349 if (mods.contains(Modifier.AUTOMATIC) && mods.size() > 1)
2350 throw new IllegalArgumentException("AUTOMATIC cannot be used with"
2351 + " other modifiers");
2352
2353 return new Builder(name, true, mods);
2354 }
2355
2356 /**
2357 * Instantiates a builder to build a module descriptor for a <em>normal</em>
2358 * module. This method is equivalent to invoking {@link #newModule(String,Set)
2359 * newModule} with an empty set of {@link ModuleDescriptor.Modifier modifiers}.
2360 *
2361 * @param name
2362 * The module name
2363 *
2364 * @return A new builder
2365 *
2366 * @throws IllegalArgumentException
2367 * If the module name is {@code null} or is not a legal module
2368 * name
2369 */
2370 public static Builder newModule(String name) {
2371 return new Builder(name, true, Set.of());
2372 }
2373
2374 /**
2375 * Instantiates a builder to build a module descriptor for an open module.
2376 * This method is equivalent to invoking {@link #newModule(String,Set)
2377 * newModule} with the {@link ModuleDescriptor.Modifier#OPEN OPEN} modifier.
2378 *
2379 * <p> The builder for an open module cannot be used to declare any open
2380 * packages. </p>
2381 *
2382 * @param name
2383 * The module name
2384 *
2385 * @return A new builder that builds an open module
2386 *
2387 * @throws IllegalArgumentException
2388 * If the module name is {@code null} or is not a legal module
2389 * name
2390 */
2391 public static Builder newOpenModule(String name) {
2392 return new Builder(name, true, Set.of(Modifier.OPEN));
2393 }
2394
2395 /**
2396 * Instantiates a builder to build a module descriptor for an automatic
2397 * module. This method is equivalent to invoking {@link #newModule(String,Set)
2398 * newModule} with the {@link ModuleDescriptor.Modifier#AUTOMATIC AUTOMATIC}
2399 * modifier.
2400 *
2401 * <p> The builder for an automatic module cannot be used to declare module
2402 * or service dependences. It also cannot be used to declare any exported
2403 * or open packages. </p>
2404 *
2405 * @param name
2406 * The module name
2407 *
2408 * @return A new builder that builds an automatic module
2409 *
2410 * @throws IllegalArgumentException
2411 * If the module name is {@code null} or is not a legal module
2412 * name
2413 *
2414 * @see ModuleFinder#of(Path[])
2415 */
2416 public static Builder newAutomaticModule(String name) {
2417 return new Builder(name, true, Set.of(Modifier.AUTOMATIC));
2418 }
2419
2420
2421 /**
2422 * Reads the binary form of a module declaration from an input stream
2423 * as a module descriptor.
2424 *
2425 * <p> If the descriptor encoded in the input stream does not indicate a
2426 * set of packages in the module then the {@code packageFinder} will be
2427 * invoked. The set of packages that the {@code packageFinder} returns
2428 * must include all the packages that the module exports, opens, as well
2429 * as the packages of the service implementations that the module provides,
2430 * and the package of the main class (if the module has a main class). If
2431 * the {@code packageFinder} throws an {@link UncheckedIOException} then
2432 * {@link IOException} cause will be re-thrown. </p>
2433 *
2434 * <p> If there are bytes following the module descriptor then it is
2435 * implementation specific as to whether those bytes are read, ignored,
2436 * or reported as an {@code InvalidModuleDescriptorException}. If this
2437 * method fails with an {@code InvalidModuleDescriptorException} or {@code
2438 * IOException} then it may do so after some, but not all, bytes have
2439 * been read from the input stream. It is strongly recommended that the
2440 * stream be promptly closed and discarded if an exception occurs. </p>
2441 *
2442 * @apiNote The {@code packageFinder} parameter is for use when reading
2443 * module descriptors from legacy module-artifact formats that do not
2444 * record the set of packages in the descriptor itself.
2445 *
2446 * @param in
2447 * The input stream
2448 * @param packageFinder
2449 * A supplier that can produce the set of packages
2450 *
2451 * @return The module descriptor
2452 *
2453 * @throws InvalidModuleDescriptorException
2454 * If an invalid module descriptor is detected or the set of
2455 * packages returned by the {@code packageFinder} does not include
2456 * all of the packages obtained from the module descriptor
2457 * @throws IOException
2458 * If an I/O error occurs reading from the input stream or {@code
2459 * UncheckedIOException} is thrown by the package finder
2460 */
2461 public static ModuleDescriptor read(InputStream in,
2462 Supplier<Set<String>> packageFinder)
2463 throws IOException
2464 {
2465 return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
2466 }
2467
2468 /**
2469 * Reads the binary form of a module declaration from an input stream as a
2470 * module descriptor. This method works exactly as specified by the 2-arg
2471 * {@link #read(InputStream,Supplier) read} method with the exception that
2472 * a packager finder is not used to find additional packages when the
2473 * module descriptor read from the stream does not indicate the set of
2474 * packages.
2475 *
2476 * @param in
2477 * The input stream
2478 *
2479 * @return The module descriptor
2480 *
2481 * @throws InvalidModuleDescriptorException
2482 * If an invalid module descriptor is detected
2483 * @throws IOException
2484 * If an I/O error occurs reading from the input stream
2485 */
2486 public static ModuleDescriptor read(InputStream in) throws IOException {
2487 return ModuleInfo.read(in, null).descriptor();
2488 }
2489
2490 /**
2491 * Reads the binary form of a module declaration from a byte buffer
2492 * as a module descriptor.
2493 *
2494 * <p> If the descriptor encoded in the byte buffer does not indicate a
2495 * set of packages in the module then the {@code packageFinder} will be
2496 * invoked. The set of packages that the {@code packageFinder} returns
2497 * must include all the packages that the module exports, opens, as well
2498 * as the packages of the service implementations that the module provides,
2499 * and the package of the main class (if the module has a main class). If
2500 * the {@code packageFinder} throws an {@link UncheckedIOException} then
2501 * {@link IOException} cause will be re-thrown. </p>
2502 *
2503 * <p> The module descriptor is read from the buffer starting at index
2504 * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
2505 * position} when this method is invoked. Upon return the buffer's position
2506 * will be equal to {@code p + n} where {@code n} is the number of bytes
2507 * read from the buffer. </p>
2508 *
2509 * <p> If there are bytes following the module descriptor then it is
2510 * implementation specific as to whether those bytes are read, ignored,
2511 * or reported as an {@code InvalidModuleDescriptorException}. If this
2512 * method fails with an {@code InvalidModuleDescriptorException} then it
2513 * may do so after some, but not all, bytes have been read. </p>
2514 *
2515 * @apiNote The {@code packageFinder} parameter is for use when reading
2516 * module descriptors from legacy module-artifact formats that do not
2517 * record the set of packages in the descriptor itself.
2518 *
2519 * @param bb
2520 * The byte buffer
2521 * @param packageFinder
2522 * A supplier that can produce the set of packages
2523 *
2524 * @return The module descriptor
2525 *
2526 * @throws InvalidModuleDescriptorException
2527 * If an invalid module descriptor is detected or the set of
2528 * packages returned by the {@code packageFinder} does not include
2529 * all of the packages obtained from the module descriptor
2530 */
2531 public static ModuleDescriptor read(ByteBuffer bb,
2532 Supplier<Set<String>> packageFinder)
2533 {
2534 return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
2535 }
2536
2537 /**
2538 * Reads the binary form of a module declaration from a byte buffer as a
2539 * module descriptor. This method works exactly as specified by the 2-arg
2540 * {@link #read(ByteBuffer,Supplier) read} method with the exception that a
2541 * packager finder is not used to find additional packages when the module
2542 * descriptor encoded in the buffer does not indicate the set of packages.
2543 *
2544 * @param bb
2545 * The byte buffer
2546 *
2547 * @return The module descriptor
2548 *
2549 * @throws InvalidModuleDescriptorException
2550 * If an invalid module descriptor is detected
2551 */
2552 public static ModuleDescriptor read(ByteBuffer bb) {
2553 return ModuleInfo.read(bb, null).descriptor();
2554 }
2555
2556 private static String packageName(String cn) {
2557 int index = cn.lastIndexOf('.');
2558 return (index == -1) ? "" : cn.substring(0, index);
2559 }
2560
2561 /**
2562 * Returns a string containing the given set of modifiers and label.
2563 */
2564 private static <M> String toString(Set<M> mods, String what) {
2565 return (Stream.concat(mods.stream().map(e -> e.toString()
2566 .toLowerCase(Locale.ROOT)),
2567 Stream.of(what)))
2568 .collect(Collectors.joining(" "));
2569 }
2570
2571 private static <T extends Object & Comparable<? super T>>
2572 int compare(T obj1, T obj2) {
2573 if (obj1 != null) {
2574 return (obj2 != null) ? obj1.compareTo(obj2) : 1;
2575 } else {
2576 return (obj2 == null) ? 0 : -1;
2577 }
2578 }
2579
2580 /**
2581 * Compares two sets of {@code Comparable} objects.
2582 */
2583 @SuppressWarnings("unchecked")
2584 private static <T extends Object & Comparable<? super T>>
2585 int compare(Set<T> s1, Set<T> s2) {
2586 T[] a1 = (T[]) s1.toArray();
2587 T[] a2 = (T[]) s2.toArray();
2588 Arrays.sort(a1);
2589 Arrays.sort(a2);
2590 return Arrays.compare(a1, a2);
2591 }
2592
2593 private static <E extends Enum<E>> long modsValue(Set<E> set) {
2594 long value = 0;
2595 for (Enum<E> e : set) {
2596 value += 1 << e.ordinal();
2597 }
2598 return value;
2599 }
2600
2601 static {
2602 /**
2603 * Setup the shared secret to allow code in other packages access
2604 * private package methods in java.lang.module.
2605 */
2606 jdk.internal.misc.SharedSecrets
2607 .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
2608 @Override
2609 public Builder newModuleBuilder(String mn,
2610 boolean strict,
2611 Set<ModuleDescriptor.Modifier> modifiers) {
2612 return new Builder(mn, strict, modifiers);
2613 }
2614
2615 @Override
2616 public Set<String> packages(ModuleDescriptor.Builder builder) {
2617 return builder.packages();
2618 }
2619
2620 @Override
2621 public void requires(ModuleDescriptor.Builder builder,
2622 Set<Requires.Modifier> ms,
2623 String mn,
2624 String rawCompiledVersion) {
2625 builder.requires(ms, mn, rawCompiledVersion);
2626 }
2627
2628 @Override
2629 public Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v) {
2630 return new Requires(ms, mn, v, true);
2631 }
2632
2633 @Override
2634 public Exports newExports(Set<Exports.Modifier> ms, String source) {
2635 return new Exports(ms, source, Set.of(), true);
2636 }
2637
2638 @Override
2639 public Exports newExports(Set<Exports.Modifier> ms,
2640 String source,
2641 Set<String> targets) {
2642 return new Exports(ms, source, targets, true);
2643 }
2644
2645 @Override
2646 public Opens newOpens(Set<Opens.Modifier> ms,
2647 String source,
2648 Set<String> targets) {
2649 return new Opens(ms, source, targets, true);
2650 }
2651
2652 @Override
2653 public Opens newOpens(Set<Opens.Modifier> ms, String source) {
2654 return new Opens(ms, source, Set.of(), true);
2655 }
2656
2657 @Override
2658 public Provides newProvides(String service, List<String> providers) {
2659 return new Provides(service, providers, true);
2660 }
2661
2662 @Override
2663 public ModuleDescriptor newModuleDescriptor(String name,
2664 Version version,
2665 Set<ModuleDescriptor.Modifier> modifiers,
2666 Set<Requires> requires,
2667 Set<Exports> exports,
2668 Set<Opens> opens,
2669 Set<String> uses,
2670 Set<Provides> provides,
2671 Set<String> packages,
2672 String mainClass,
2673 int hashCode) {
2674 return new ModuleDescriptor(name,
2675 version,
2676 modifiers,
2677 requires,
2678 exports,
2679 opens,
2680 uses,
2681 provides,
2682 packages,
2683 mainClass,
2684 hashCode,
2685 false);
2686 }
2687
2688 @Override
2689 public Configuration resolveAndBind(ModuleFinder finder,
2690 Collection<String> roots,
2691 PrintStream traceOutput)
2692 {
2693 return Configuration.resolveAndBind(finder, roots, traceOutput);
2694 }
2695
2696 @Override
2697 public Configuration newConfiguration(ModuleFinder finder,
2698 Map<String, Set<String>> graph) {
2699 return new Configuration(finder, graph);
2700 }
2701 });
2702 }
2703
2704 }
2705