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