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