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