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