8200127: Replace collection.stream().forEach() with collection.forEach()
Reviewed-by: alanb

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