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