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