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