< prev index next >

src/java.base/share/classes/java/lang/module/ModuleDescriptor.java

Print this page


   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.nio.ByteBuffer;
  33 import java.nio.file.Path;
  34 import java.util.ArrayList;
  35 import java.util.Collection;
  36 import java.util.Collections;
  37 import java.util.EnumSet;
  38 import java.util.HashMap;
  39 import java.util.HashSet;

  40 import java.util.List;
  41 import java.util.Map;
  42 import java.util.Objects;
  43 import java.util.Optional;
  44 import java.util.Set;

  45 import java.util.function.Supplier;
  46 import java.util.stream.Collectors;
  47 import java.util.stream.Stream;
  48 
  49 import static jdk.internal.module.Checks.*;
  50 import static java.util.Objects.*;
  51 
  52 import jdk.internal.module.Checks;
  53 import jdk.internal.module.ModuleInfo;
  54 
  55 
  56 /**
  57  * A module descriptor.
  58  *
  59  * <p> A {@code ModuleDescriptor} is typically created from the binary form
  60  * of a module declaration. Alternatively, the {@link ModuleDescriptor.Builder}
  61  * class can be used to create a {@code ModuleDescriptor} from its components.
  62  * The {@link #module module}, {@link #openModule openModule}, and {@link
  63  * #automaticModule automaticModule} methods create builders for building
  64  * different kinds of modules. </p>


















  65  *
  66  * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
  67  * multiple concurrent threads.</p>
  68  *
  69  * @since 9
  70  * @see java.lang.reflect.Module


  71  */
  72 
  73 public class ModuleDescriptor
  74     implements Comparable<ModuleDescriptor>
  75 {
  76 
  77     /**


































  78      * <p> A dependence upon a module </p>
  79      *
  80      * @see ModuleDescriptor#requires()
  81      * @since 9

  82      */
  83 
  84     public final static class Requires
  85         implements Comparable<Requires>
  86     {
  87 
  88         /**
  89          * A modifier on a module dependence.
  90          *

  91          * @since 9

  92          */
  93         public static enum Modifier {
  94 
  95             /**
  96              * The dependence causes any module which depends on the <i>current
  97              * module</i> to have an implicitly declared dependence on the module
  98              * named by the {@code Requires}.
  99              */
 100             TRANSITIVE,
 101 
 102             /**
 103              * The dependence is mandatory in the static phase, during compilation,
 104              * but is optional in the dynamic phase, during execution.
 105              */
 106             STATIC,
 107 
 108             /**
 109              * The dependence was not explicitly or implicitly declared in the
 110              * source of the module declaration.
 111              */


 154          *
 155          * @return The module name
 156          */
 157         public String name() {
 158             return name;
 159         }
 160 
 161         /**
 162          * Returns the version of the module if recorded at compile-time.
 163          *
 164          * @return The version of the module if recorded at compile-time
 165          */
 166         public Optional<Version> compiledVersion() {
 167             return Optional.ofNullable(compiledVersion);
 168         }
 169 
 170         /**
 171          * Compares this module dependence to another.
 172          *
 173          * <p> Two {@code Requires} objects are compared by comparing their
 174          * module name lexicographically.  Where the module names are equal then
 175          * the sets of modifiers are compared based on a value computed from the
 176          * ordinal of each modifier. Where the module names are equal and the
 177          * set of modifiers are equal then the version of the modules recorded
 178          * at compile-time are compared. When comparing the versions recorded
 179          * at compile-time then a dependence that has a recorded version is
 180          * considered to succeed a dependence that does not have a recorded
 181          * version. </p>




 182          *
 183          * @return A negative integer, zero, or a positive integer if this module
 184          *         dependence is less than, equal to, or greater than the given
 185          *         module dependence
 186          */
 187         @Override
 188         public int compareTo(Requires that) {


 189             int c = this.name().compareTo(that.name());
 190             if (c != 0)
 191                 return c;
 192 
 193             // modifiers
 194             c = Long.compare(this.modsValue(), that.modsValue());
 195             if (c != 0)
 196                 return c;

 197 
 198             // compiledVersion
 199             if (this.compiledVersion != null) {
 200                 if (that.compiledVersion != null)
 201                     c = this.compiledVersion.compareTo(that.compiledVersion);
 202                 else
 203                     c = 1;
 204             } else {
 205                 if (that.compiledVersion != null)
 206                     c = -1;
 207             }
 208 
 209             return c;
 210         }
 211 
 212         /**
 213          * Return a value for the modifiers to allow sets of modifiers to be
 214          * compared.
 215          */
 216         private long modsValue() {
 217             long value = 0;
 218             for (Modifier m : mods) {
 219                 value += 1 << m.ordinal();
 220             }
 221             return value;
 222         }
 223 
 224         /**
 225          * Tests this module dependence for equality with the given object.
 226          *
 227          * <p> If the given object is not a {@code Requires} then this method
 228          * returns {@code false}. Two module dependence objects are equal if
 229          * the module names are equal, set of modifiers are equal, and the
 230          * compiled version of both modules is equal or not recorded for
 231          * both modules. </p>
 232          *
 233          * <p> This method satisfies the general contract of the {@link
 234          * java.lang.Object#equals(Object) Object.equals} method. </p>
 235          *
 236          * @param   ob
 237          *          the object to which this object is to be compared
 238          *
 239          * @return  {@code true} if, and only if, the given object is a module
 240          *          dependence that is equal to this module dependence
 241          */


 249         }
 250 
 251         /**
 252          * Computes a hash code for this module dependence.
 253          *
 254          * <p> The hash code is based upon the module name, modifiers, and the
 255          * module version if recorded at compile time. It satisfies the general
 256          * contract of the {@link Object#hashCode Object.hashCode} method. </p>
 257          *
 258          * @return The hash-code value for this module dependence
 259          */
 260         @Override
 261         public int hashCode() {
 262             int hash = name.hashCode() * 43 + mods.hashCode();
 263             if (compiledVersion != null)
 264                 hash = hash * 43 + compiledVersion.hashCode();
 265             return hash;
 266         }
 267 
 268         /**
 269          * Returns a string describing module dependence.
 270          *
 271          * @return A string describing module dependence
 272          */
 273         @Override
 274         public String toString() {
 275             String what;
 276             if (compiledVersion != null) {
 277                 what = name() + " (@" + compiledVersion + ")";
 278             } else {
 279                 what = name();
 280             }
 281             return ModuleDescriptor.toString(mods, what);
 282         }
 283     }
 284 
 285 
 286 
 287     /**
 288      * <p> A module export, may be qualified or unqualified. </p>
 289      *
 290      * @see ModuleDescriptor#exports()
 291      * @since 9

 292      */
 293 
 294     public final static class Exports {


 295 
 296         /**
 297          * A modifier on a module export.
 298          *

 299          * @since 9

 300          */
 301         public static enum Modifier {
 302 
 303             /**
 304              * The export was not explicitly or implicitly declared in the
 305              * source of the module declaration.
 306              */
 307             SYNTHETIC,
 308 
 309             /**
 310              * The export was implicitly declared in the source of the module
 311              * declaration.
 312              */
 313             MANDATED;
 314 
 315         }
 316 
 317         private final Set<Modifier> mods;
 318         private final String source;
 319         private final Set<String> targets;  // empty if unqualified export


 364          *
 365          * @return The package name
 366          */
 367         public String source() {
 368             return source;
 369         }
 370 
 371         /**
 372          * For a qualified export, returns the non-empty and immutable set
 373          * of the module names to which the package is exported. For an
 374          * unqualified export, returns an empty set.
 375          *
 376          * @return The set of target module names or for an unqualified
 377          *         export, an empty set
 378          */
 379         public Set<String> targets() {
 380             return targets;
 381         }
 382 
 383         /**













































 384          * Computes a hash code for this module export.
 385          *
 386          * <p> The hash code is based upon the modifiers, the package name,
 387          * and for a qualified export, the set of modules names to which the
 388          * package is exported. It satisfies the general contract of the
 389          * {@link Object#hashCode Object.hashCode} method.
 390          *
 391          * @return The hash-code value for this module export
 392          */
 393         @Override
 394         public int hashCode() {
 395             int hash = mods.hashCode();
 396             hash = hash * 43 + source.hashCode();
 397             return hash * 43 + targets.hashCode();
 398         }
 399 
 400         /**
 401          * Tests this module export for equality with the given object.
 402          *
 403          * <p> If the given object is not an {@code Exports} then this method


 408          * <p> This method satisfies the general contract of the {@link
 409          * java.lang.Object#equals(Object) Object.equals} method. </p>
 410          *
 411          * @param   ob
 412          *          the object to which this object is to be compared
 413          *
 414          * @return  {@code true} if, and only if, the given object is a module
 415          *          dependence that is equal to this module dependence
 416          */
 417         @Override
 418         public boolean equals(Object ob) {
 419             if (!(ob instanceof Exports))
 420                 return false;
 421             Exports other = (Exports)ob;
 422             return Objects.equals(this.mods, other.mods)
 423                     && Objects.equals(this.source, other.source)
 424                     && Objects.equals(this.targets, other.targets);
 425         }
 426 
 427         /**
 428          * Returns a string describing module export.
 429          *
 430          * @return A string describing module export
 431          */
 432         @Override
 433         public String toString() {
 434             String s = ModuleDescriptor.toString(mods, source);
 435             if (targets.isEmpty())
 436                 return s;
 437             else
 438                 return s + " to " + targets;
 439         }
 440     }
 441 
 442 
 443     /**
 444      * <p> Represents a module <em>opens</em> directive, may be qualified or
 445      * unqualified. </p>
 446      *
 447      * <p> The <em>opens</em> directive in a module declaration declares a
 448      * package to be open to allow all types in the package, and all their
 449      * members, not just public types and their public members to be reflected
 450      * on by APIs that support private access or a way to bypass or suppress
 451      * default Java language access control checks. </p>
 452      *
 453      * @see ModuleDescriptor#opens()
 454      * @since 9

 455      */
 456 
 457     public final static class Opens {
 458 

 459         /**
 460          * A modifier on a module <em>opens</em> directive.
 461          *

 462          * @since 9

 463          */
 464         public static enum Modifier {
 465 
 466             /**
 467              * The opens was not explicitly or implicitly declared in the
 468              * source of the module declaration.
 469              */
 470             SYNTHETIC,
 471 
 472             /**
 473              * The opens was implicitly declared in the source of the module
 474              * declaration.
 475              */
 476             MANDATED;
 477 
 478         }
 479 
 480         private final Set<Modifier> mods;
 481         private final String source;
 482         private final Set<String> targets;  // empty if unqualified export
 483 
 484         /**
 485          * Constructs an Opens
 486          */
 487         private Opens(Set<Modifier> ms, String source, Set<String> targets) {
 488             if (ms.isEmpty()) {
 489                 ms = Collections.emptySet();
 490             } else {
 491                 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
 492             }
 493             this.mods = ms;
 494             this.source = source;


 527          *
 528          * @return The package name
 529          */
 530         public String source() {
 531             return source;
 532         }
 533 
 534         /**
 535          * For a qualified opens, returns the non-empty and immutable set
 536          * of the module names to which the package is open. For an
 537          * unqualified opens, returns an empty set.
 538          *
 539          * @return The set of target module names or for an unqualified
 540          *         opens, an empty set
 541          */
 542         public Set<String> targets() {
 543             return targets;
 544         }
 545 
 546         /**













































 547          * Computes a hash code for this module opens.
 548          *
 549          * <p> The hash code is based upon the modifiers, the package name,
 550          * and for a qualified opens, the set of modules names to which the
 551          * package is opened. It satisfies the general contract of the
 552          * {@link Object#hashCode Object.hashCode} method.
 553          *
 554          * @return The hash-code value for this module opens
 555          */
 556         @Override
 557         public int hashCode() {
 558             int hash = mods.hashCode();
 559             hash = hash * 43 + source.hashCode();
 560             return hash * 43 + targets.hashCode();
 561         }
 562 
 563         /**
 564          * Tests this module opens for equality with the given object.
 565          *
 566          * <p> If the given object is not an {@code Opens} then this method


 571          * <p> This method satisfies the general contract of the {@link
 572          * java.lang.Object#equals(Object) Object.equals} method. </p>
 573          *
 574          * @param   ob
 575          *          the object to which this object is to be compared
 576          *
 577          * @return  {@code true} if, and only if, the given object is a module
 578          *          dependence that is equal to this module dependence
 579          */
 580         @Override
 581         public boolean equals(Object ob) {
 582             if (!(ob instanceof Opens))
 583                 return false;
 584             Opens other = (Opens)ob;
 585             return Objects.equals(this.mods, other.mods)
 586                     && Objects.equals(this.source, other.source)
 587                     && Objects.equals(this.targets, other.targets);
 588         }
 589 
 590         /**
 591          * Returns a string describing module opens.
 592          *
 593          * @return A string describing module opens
 594          */
 595         @Override
 596         public String toString() {
 597             String s = ModuleDescriptor.toString(mods, source);
 598             if (targets.isEmpty())
 599                 return s;
 600             else
 601                 return s + " to " + targets;
 602         }
 603     }
 604 
 605 
 606     /**
 607      * <p> A service that a module provides one or more implementations of. </p>
 608      *
 609      * @see ModuleDescriptor#provides()
 610      * @since 9

 611      */
 612 
 613     public final static class Provides {
 614 

 615         private final String service;
 616         private final List<String> providers;
 617 
 618         private Provides(String service, List<String> providers) {
 619             this.service = service;
 620             this.providers = Collections.unmodifiableList(providers);
 621         }
 622 
 623         private Provides(String service, List<String> providers, boolean unused) {
 624             this.service = service;
 625             this.providers = providers;
 626         }
 627 
 628         /**
 629          * Returns the fully qualified class name of the service type.
 630          *
 631          * @return The fully qualified class name of the service type.
 632          */
 633         public String service() { return service; }
 634 
 635         /**
 636          * Returns the list of the fully qualified class names of the providers
 637          * or provider factories.
 638          *
 639          * @return A non-empty and unmodifiable list of the fully qualified class
 640          *         names of the providers or provider factories
 641          */
 642         public List<String> providers() { return providers; }
 643 
 644         /**








































 645          * Computes a hash code for this provides.
 646          *
 647          * <p> The hash code is based upon the service type and the set of
 648          * providers. It satisfies the general contract of the {@link
 649          * Object#hashCode Object.hashCode} method. </p>
 650          *
 651          * @return The hash-code value for this module provides
 652          */
 653         @Override
 654         public int hashCode() {
 655             return service.hashCode() * 43 + providers.hashCode();
 656         }
 657 
 658         /**
 659          * Tests this provides for equality with the given object.
 660          *
 661          * <p> If the given object is not a {@code Provides} then this method
 662          * returns {@code false}. Two {@code Provides} objects are equal if the
 663          * service type is equal and the list of providers is equal. </p>
 664          *


 682 
 683         /**
 684          * Returns a string describing this provides.
 685          *
 686          * @return A string describing this provides
 687          */
 688         @Override
 689         public String toString() {
 690             return service + " with " + providers;
 691         }
 692 
 693     }
 694 
 695 
 696 
 697     /**
 698      * A module's version string.
 699      *
 700      * <p> A version string has three components: The version number itself, an
 701      * optional pre-release version, and an optional build version.  Each
 702      * component is sequence of tokens; each token is either a non-negative
 703      * integer or a string.  Tokens are separated by the punctuation characters
 704      * {@code '.'}, {@code '-'}, or {@code '+'}, or by transitions from a
 705      * sequence of digits to a sequence of characters that are neither digits
 706      * nor punctuation characters, or vice versa.
 707      *
 708      * <ul>
 709      *
 710      *   <li> The <i>version number</i> is a sequence of tokens separated by
 711      *   {@code '.'} characters, terminated by the first {@code '-'} or {@code
 712      *   '+'} character. </li>
 713      *
 714      *   <li> The <i>pre-release version</i> is a sequence of tokens separated
 715      *   by {@code '.'} or {@code '-'} characters, terminated by the first
 716      *   {@code '+'} character. </li>
 717      *
 718      *   <li> The <i>build version</i> is a sequence of tokens separated by
 719      *   {@code '.'}, {@code '-'}, or {@code '+'} characters.
 720      *
 721      * </ul>
 722      *
 723      * <p> When comparing two version strings, the elements of their
 724      * corresponding components are compared in pointwise fashion.  If one
 725      * component is longer than the other, but otherwise equal to it, then the
 726      * first component is considered the greater of the two; otherwise, if two
 727      * corresponding elements are integers then they are compared as such;
 728      * otherwise, at least one of the elements is a string, so the other is
 729      * converted into a string if it is an integer and the two are compared
 730      * lexicographically.  Trailing integer elements with the value zero are
 731      * ignored.
 732      *
 733      * <p> Given two version strings, if their version numbers differ then the
 734      * result of comparing them is the result of comparing their version
 735      * numbers; otherwise, if one of them has a pre-release version but the
 736      * other does not then the first is considered to precede the second,
 737      * otherwise the result of comparing them is the result of comparing their
 738      * pre-release versions; otherwise, the result of comparing them is the
 739      * result of comparing their build versions.
 740      *
 741      * @see ModuleDescriptor#version()
 742      * @since 9

 743      */
 744 
 745     public final static class Version
 746         implements Comparable<Version>
 747     {
 748 
 749         private final String version;
 750 
 751         // If Java had disjunctive types then we'd write List<Integer|String> here
 752         //
 753         private final List<Object> sequence;
 754         private final List<Object> pre;
 755         private final List<Object> build;
 756 
 757         // Take a numeric token starting at position i
 758         // Append it to the given list
 759         // Return the index of the first character not taken
 760         // Requires: s.charAt(i) is (decimal) numeric
 761         //
 762         private static int takeNumber(String s, int i, List<Object> acc) {


 995         @Override
 996         public int hashCode() {
 997             return version.hashCode();
 998         }
 999 
1000         /**
1001          * Returns the string from which this version was parsed.
1002          *
1003          * @return The string from which this version was parsed.
1004          */
1005         @Override
1006         public String toString() {
1007             return version;
1008         }
1009 
1010     }
1011 
1012 
1013     private final String name;
1014     private final Version version;
1015     private final boolean open;
1016 
1017     // Indicates if synthesised for a JAR file found on the module path
1018     private final boolean automatic;
1019 
1020     // Not generated from a module-info.java
1021     private final boolean synthetic;
1022 
1023     private final Set<Requires> requires;
1024     private final Set<Exports> exports;
1025     private final Set<Opens> opens;
1026     private final Set<String> uses;
1027     private final Set<Provides> provides;
1028 
1029     // Added post-compilation by tools
1030     private final Set<String> packages;
1031     private final String mainClass;
1032     private final String osName;
1033     private final String osArch;
1034     private final String osVersion;
1035 
1036 
1037     private ModuleDescriptor(String name,
1038                              Version version,
1039                              boolean open,
1040                              boolean automatic,
1041                              boolean synthetic,
1042                              Set<Requires> requires,
1043                              Set<Exports> exports,
1044                              Set<Opens> opens,
1045                              Set<String> uses,
1046                              Set<Provides> provides,
1047                              Set<String> packages,
1048                              String mainClass,
1049                              String osName,
1050                              String osArch,
1051                              String osVersion)
1052     {
1053         this.name = name;
1054         this.version = version;
1055         this.open = open;
1056         this.automatic = automatic;
1057         this.synthetic = synthetic;
1058 
1059         assert (requires.stream().map(Requires::name).distinct().count()
1060                 == requires.size());
1061         this.requires = emptyOrUnmodifiableSet(requires);
1062         this.exports = emptyOrUnmodifiableSet(exports);
1063         this.opens = emptyOrUnmodifiableSet(opens);
1064         this.uses = emptyOrUnmodifiableSet(uses);
1065         this.provides = emptyOrUnmodifiableSet(provides);
1066 
1067         this.packages = emptyOrUnmodifiableSet(packages);
1068         this.mainClass = mainClass;
1069         this.osName = osName;
1070         this.osArch = osArch;
1071         this.osVersion = osVersion;
1072     }
1073 
1074     /**
1075      * Clones the given module descriptor with an augmented set of packages
1076      */
1077     ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) {
1078         this.name = md.name;
1079         this.version = md.version;
1080         this.open = md.open;
1081         this.automatic = md.automatic;
1082         this.synthetic = md.synthetic;
1083 
1084         this.requires = md.requires;
1085         this.exports = md.exports;
1086         this.opens = md.opens;
1087         this.uses = md.uses;
1088         this.provides = md.provides;
1089 
1090         Set<String> packages = new HashSet<>(md.packages);
1091         packages.addAll(pkgs);
1092         this.packages = emptyOrUnmodifiableSet(packages);
1093 
1094         this.mainClass = md.mainClass;
1095         this.osName = md.osName;
1096         this.osArch = md.osArch;
1097         this.osVersion = md.osVersion;
1098     }
1099 
1100     /**
1101      * Creates a module descriptor from its components.
1102      * The arguments are pre-validated and sets are unmodifiable sets.
1103      */
1104     ModuleDescriptor(String name,
1105                      Version version,
1106                      boolean open,
1107                      boolean automatic,
1108                      boolean synthetic,
1109                      Set<Requires> requires,
1110                      Set<Exports> exports,
1111                      Set<Opens> opens,
1112                      Set<String> uses,
1113                      Set<Provides> provides,
1114                      Set<String> packages,
1115                      String mainClass,
1116                      String osName,
1117                      String osArch,
1118                      String osVersion,
1119                      int hashCode,
1120                      boolean unused) {
1121         this.name = name;
1122         this.version = version;
1123         this.open = open;
1124         this.automatic = automatic;
1125         this.synthetic = synthetic;
1126         this.requires = requires;
1127         this.exports = exports;
1128         this.opens = opens;
1129         this.uses = uses;
1130         this.provides = provides;
1131         this.packages = packages;
1132         this.mainClass = mainClass;
1133         this.osName = osName;
1134         this.osArch = osArch;
1135         this.osVersion = osVersion;
1136         this.hash = hashCode;
1137     }
1138 
1139     /**
1140      * <p> The module name. </p>
1141      *
1142      * @return The module name
1143      */
1144     public String name() {
1145         return name;
1146     }
1147 
1148     /**









1149      * <p> Returns {@code true} if this is an open module. </p>
1150      *
1151      * <p> An open module does not declare any open packages (the {@link #opens()
1152      * opens} method returns an empty set) but the resulting module is treated
1153      * as if all packages are open. </p>
1154      *
1155      * @return  {@code true} if this is an open module
1156      */
1157     public boolean isOpen() {
1158         return open;
1159     }
1160 
1161     /**
1162      * <p> Returns {@code true} if this is an automatic module. </p>
1163      *
1164      * <p> An automatic module is defined implicitly rather than explicitly
1165      * and therefore does not have a module declaration. JAR files located on
1166      * the application module path, or by the {@link ModuleFinder} returned by
1167      * {@link ModuleFinder#of(java.nio.file.Path[]) ModuleFinder.of}, are
1168      * treated as automatic modules if they do have not have a module
1169      * declaration. </p>
1170      *
1171      * @return  {@code true} if this is an automatic module
1172      */
1173     public boolean isAutomatic() {
1174         return automatic;
1175     }
1176 
1177     /**
1178      * <p> Returns {@code true} if this module descriptor was not generated
1179      * from an explicit module declaration ({@code module-info.java})
1180      * or an implicit module declaration (an {@link #isAutomatic() automatic}
1181      * module). </p>
1182      *
1183      * @return  {@code true} if this module descriptor was not generated by
1184      *          an explicit or implicit module declaration
1185      */
1186     public boolean isSynthetic() {
1187         return synthetic;
1188     }
1189 
1190     /**
1191      * <p> The dependences of this module. </p>
1192      *
1193      * @return  A possibly-empty unmodifiable set of {@link Requires} objects
1194      */
1195     public Set<Requires> requires() {
1196         return requires;
1197     }
1198 
1199     /**
1200      * <p> The module exports. </p>



1201      *
1202      * @return  A possibly-empty unmodifiable set of exported packages
1203      */
1204     public Set<Exports> exports() {
1205         return exports;
1206     }
1207 
1208     /**
1209      * <p> The module <em>opens</em> directives. </p>
1210      *
1211      * <p> Each {@code Opens} object in the set represents a package (and
1212      * the set of target module names when qualified) where all types in the
1213      * package, and all their members, not just public types and their public
1214      * members, can be reflected on when using APIs that bypass or suppress
1215      * default Java language access control checks. </p>
1216      *
1217      * <p> This method returns an empty set when invoked on {@link #isOpen()
1218      * open} module. </p>
1219      *
1220      * @return  A possibly-empty unmodifiable set of open packages
1221      */
1222     public Set<Opens> opens() {
1223         return opens;
1224     }
1225 
1226     /**
1227      * <p> The service dependences of this module. </p>



1228      *
1229      * @return  A possibly-empty unmodifiable set of the fully qualified class
1230      *          names of the service types used
1231      */
1232     public Set<String> uses() {
1233         return uses;
1234     }
1235 
1236     /**
1237      * <p> The services that this module provides. </p>
1238      *
1239      * @return The possibly-empty unmodifiable set of the services that this
1240      *         module provides
1241      */
1242     public Set<Provides> provides() {
1243         return provides;
1244     }
1245 
1246     /**
1247      * Returns this module's version.
1248      *
1249      * @return This module's version
1250      */
1251     public Optional<Version> version() {
1252         return Optional.ofNullable(version);
1253     }
1254 
1255     /**
1256      * Returns a string containing this module's name and, if present, its
1257      * version.
1258      *
1259      * @return A string containing this module's name and, if present, its
1260      *         version.
1261      */
1262     public String toNameAndVersion() {
1263         if (version != null) {
1264             return name() + "@" + version;
1265         } else {
1266             return name();
1267         }
1268     }
1269 
1270     /**
1271      * Returns the module's main class.
1272      *
1273      * @return The fully qualified class name of this module's main class
1274      */
1275     public Optional<String> mainClass() {
1276         return Optional.ofNullable(mainClass);
1277     }
1278 
1279     /**
1280      * Returns the operating system name if this module is operating system
1281      * specific.
1282      *
1283      * @return The operating system name or an empty {@code Optional}
1284      *         if this module is not operating system specific
1285      */
1286     public Optional<String> osName() {
1287         return Optional.ofNullable(osName);
1288     }
1289 
1290     /**
1291      * Returns the operating system architecture if this module is operating
1292      * system architecture specific.
1293      *
1294      * @return The operating system architecture or an empty {@code Optional}
1295      *         if this module is not operating system architecture specific
1296      */
1297     public Optional<String> osArch() {
1298         return Optional.ofNullable(osArch);
1299     }
1300 
1301     /**
1302      * Returns the operating system version if this module is operating
1303      * system version specific.
1304      *
1305      * @return The operating system version or an empty {@code Optional}
1306      *         if this module is not operating system version specific
1307      */
1308     public Optional<String> osVersion() {
1309         return Optional.ofNullable(osVersion);
1310     }
1311 
1312     /**
1313      * Returns the names of all packages in this module.
1314      *
1315      * @return A possibly-empty unmodifiable set of all packages in the module
1316      */
1317     public Set<String> packages() {
1318         return packages;
1319     }
1320 
1321 
1322     /**
1323      * A builder used for building {@link ModuleDescriptor} objects.
1324      *
1325      * <p> {@code ModuleDescriptor} defines the {@link #module module}, {@link
1326      * #openModule openModule}, and {@link #automaticModule automaticModule}
1327      * methods to create builders for building different kinds of modules. </p>














1328      *
1329      * <p> Example usage: </p>
1330      * <pre>{@code    ModuleDescriptor descriptor = ModuleDescriptor.module("m1")
1331      *         .exports("p")
1332      *         .requires("m2")


1333      *         .build();
1334      * }</pre>
1335      *
1336      * @apiNote A {@code Builder} checks the components and invariants as
1337      * components are added to the builder. The rational for this is to detect
1338      * errors as early as possible and not defer all validation to the
1339      * {@link #build build} method. A {@code Builder} cannot be used to create
1340      * a {@link ModuleDescriptor#isSynthetic() synthetic} module.
1341      *
1342      * @since 9

1343      */
1344     public static final class Builder {
1345         final String name;
1346         final boolean strict; // true if module names are checked

1347         final boolean open;
1348         final boolean synthetic;
1349         boolean automatic;
1350         final Map<String, Requires> requires = new HashMap<>();
1351         final Map<String, Exports> exports = new HashMap<>();
1352         final Map<String, Opens> opens = new HashMap<>();
1353         final Set<String> concealedPackages = new HashSet<>();
1354         final Set<String> uses = new HashSet<>();
1355         final Map<String, Provides> provides = new HashMap<>();
1356         Version version;
1357         String osName;
1358         String osArch;
1359         String osVersion;
1360         String mainClass;
1361 
1362         /**
1363          * Initializes a new builder with the given module name.
1364          *
1365          * @param strict
1366          *        Indicates whether module names are checked or not


1367          */
1368         Builder(String name, boolean strict, boolean open, boolean synthetic) {
1369             this.name = (strict) ? requireModuleName(name) : name;
1370             this.strict = strict;
1371             this.open = open;
1372             this.synthetic = synthetic;
1373         }
1374 
1375         /* package */ Builder automatic(boolean automatic) {
1376             this.automatic = automatic;
1377             return this;
1378         }
1379 
1380         /**
1381          * Returns the set of packages that are exported (unconditionally or
1382          * unconditionally).
1383          */
1384         /* package */ Set<String> exportedPackages() {
1385             return exports.keySet();
1386         }
1387 
1388         /**
1389          * Returns the set of packages that are opened (unconditionally or
1390          * unconditionally).
1391          */
1392         /* package */Set<String> openPackages() {
1393             return opens.keySet();
1394         }
1395 
1396         /**
1397          * Adds a dependence on a module.
1398          *
1399          * @param  req
1400          *         The dependence
1401          *
1402          * @return This builder
1403          *
1404          * @throws IllegalArgumentException
1405          *         If the dependence is on the module that this builder was
1406          *         initialized to build
1407          * @throws IllegalStateException
1408          *         If the dependence on the module has already been declared

1409          */
1410         public Builder requires(Requires req) {



1411             String mn = req.name();
1412             if (name.equals(mn))
1413                 throw new IllegalArgumentException("Dependence on self");
1414             if (requires.containsKey(mn))
1415                 throw new IllegalStateException("Dependence upon " + mn
1416                                                 + " already declared");
1417             requires.put(mn, req);
1418             return this;
1419         }
1420 
1421         /**
1422          * Adds a dependence on a module with the given (and possibly empty)
1423          * set of modifiers. The dependence includes the version of the
1424          * module that that was recorded at compile-time.
1425          *
1426          * @param  ms
1427          *         The set of modifiers
1428          * @param  mn
1429          *         The module name
1430          * @param  compiledVersion
1431          *         The version of the module recorded at compile-time
1432          *
1433          * @return This builder
1434          *
1435          * @throws IllegalArgumentException
1436          *         If the module name is {@code null}, is not a legal Java
1437          *         identifier, or is equal to the module name that this builder
1438          *         was initialized to build
1439          * @throws IllegalStateException
1440          *         If the dependence on the module has already been declared

1441          */
1442         public Builder requires(Set<Requires.Modifier> ms,
1443                                 String mn,
1444                                 Version compiledVersion) {
1445             Objects.requireNonNull(compiledVersion);
1446             if (strict)
1447                 mn = requireModuleName(mn);
1448             return requires(new Requires(ms, mn, compiledVersion));
1449         }
1450 

















1451         /**
1452          * Adds a dependence on a module with the given (and possibly empty)
1453          * set of modifiers.
1454          *
1455          * @param  ms
1456          *         The set of modifiers
1457          * @param  mn
1458          *         The module name
1459          *
1460          * @return This builder
1461          *
1462          * @throws IllegalArgumentException
1463          *         If the module name is {@code null}, is not a legal Java
1464          *         identifier, or is equal to the module name that this builder
1465          *         was initialized to build
1466          * @throws IllegalStateException
1467          *         If the dependence on the module has already been declared

1468          */
1469         public Builder requires(Set<Requires.Modifier> ms, String mn) {
1470             if (strict)
1471                 mn = requireModuleName(mn);
1472             return requires(new Requires(ms, mn, null));
1473         }
1474 
1475         /**
1476          * Adds a dependence on a module with an empty set of modifiers.
1477          *
1478          * @param  mn
1479          *         The module name
1480          *
1481          * @return This builder
1482          *
1483          * @throws IllegalArgumentException
1484          *         If the module name is {@code null}, is not a legal Java
1485          *         identifier, or is equal to the module name that this builder
1486          *         was initialized to build
1487          * @throws IllegalStateException
1488          *         If the dependence on the module has already been declared

1489          */
1490         public Builder requires(String mn) {
1491             return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
1492         }
1493 
1494         /**
1495          * Adds an export.
1496          *
1497          * @param  e
1498          *         The export
1499          *
1500          * @return This builder
1501          *
1502          * @throws IllegalStateException
1503          *         If the package is already declared as a package with the
1504          *         {@link #contains contains} method or the package is already
1505          *         declared as exported
1506          */
1507         public Builder exports(Exports e) {
1508             // can't be exported and concealed
1509             String source = e.source();
1510             if (concealedPackages.contains(source)) {
1511                 throw new IllegalStateException("Package " + source
1512                                                  + " already declared");
1513             }

1514             if (exports.containsKey(source)) {
1515                 throw new IllegalStateException("Exported package " + source
1516                                                  + " already declared");
1517             }
1518 
1519             exports.put(source, e);

1520             return this;
1521         }
1522 
1523         /**
1524          * Adds an export, with the given (and possibly empty) set of modifiers,
1525          * to export a package to a set of target modules.
1526          *
1527          * @param  ms
1528          *         The set of modifiers
1529          * @param  pn
1530          *         The package name
1531          * @param  targets
1532          *         The set of target modules names
1533          *
1534          * @return This builder
1535          *
1536          * @throws IllegalArgumentException
1537          *         If the package name or any of the target modules is {@code
1538          *         null} or is not a legal Java identifier, or the set of
1539          *         targets is empty

1540          * @throws IllegalStateException
1541          *         If the package is already declared as a package with the
1542          *         {@link #contains contains} method or the package is already
1543          *         declared as exported
1544          */
1545         public Builder exports(Set<Exports.Modifier> ms,
1546                                String pn,
1547                                Set<String> targets)
1548         {
1549             Exports e = new Exports(ms, requirePackageName(pn), targets);
1550 
1551             // check targets
1552             targets = e.targets();
1553             if (targets.isEmpty())
1554                 throw new IllegalArgumentException("Empty target set");
1555             if (strict)

1556                 targets.stream().forEach(Checks::requireModuleName);
1557 
1558             return exports(e);
1559         }
1560 
1561         /**
1562          * Adds an unqualified export with the given (and possibly empty) set
1563          * of modifiers.
1564          *
1565          * @param  ms
1566          *         The set of modifiers
1567          * @param  pn
1568          *         The package name
1569          *
1570          * @return This builder
1571          *
1572          * @throws IllegalArgumentException
1573          *         If the package name is {@code null} or is not a legal Java
1574          *         identifier
1575          * @throws IllegalStateException
1576          *         If the package is already declared as a package with the
1577          *         {@link #contains contains} method or the package is already
1578          *         declared as exported
1579          */
1580         public Builder exports(Set<Exports.Modifier> ms, String pn) {
1581             Exports e = new Exports(ms, requirePackageName(pn), Collections.emptySet());



1582             return exports(e);
1583         }
1584 
1585         /**
1586          * Adds an export to export a package to a set of target modules.

1587          *
1588          * @param  pn
1589          *         The package name
1590          * @param  targets
1591          *         The set of target modules names
1592          *
1593          * @return This builder
1594          *
1595          * @throws IllegalArgumentException
1596          *         If the package name or any of the target modules is {@code
1597          *         null} or is not a legal Java identifier, or the set of
1598          *         targets is empty

1599          * @throws IllegalStateException
1600          *         If the package is already declared as a package with the
1601          *         {@link #contains contains} method or the package is already
1602          *         declared as exported
1603          */
1604         public Builder exports(String pn, Set<String> targets) {
1605             return exports(Collections.emptySet(), pn, targets);
1606         }
1607 
1608         /**
1609          * Adds an unqualified export.
1610          *
1611          * @param  pn
1612          *         The package name
1613          *
1614          * @return This builder
1615          *
1616          * @throws IllegalArgumentException
1617          *         If the package name is {@code null} or is not a legal Java
1618          *         identifier
1619          * @throws IllegalStateException
1620          *         If the package is already declared as a package with the
1621          *         {@link #contains contains} method or the package is already
1622          *         declared as exported
1623          */
1624         public Builder exports(String pn) {
1625             return exports(Collections.emptySet(), pn);
1626         }
1627 
1628         /**
1629          * Adds an <em>opens</em> directive.
1630          *
1631          * @param  obj
1632          *         The {@code Opens} object
1633          *
1634          * @return This builder
1635          *
1636          * @throws IllegalStateException
1637          *         If the package is already declared as a package with the
1638          *         {@link #contains contains} method, the package is already
1639          *         declared as open, or this is a builder for an open module
1640          */
1641         public Builder opens(Opens obj) {
1642             if (open) {
1643                 throw new IllegalStateException("open modules cannot declare"
1644                                                 + " open packages");
1645             }
1646 
1647             // can't be open and concealed
1648             String source = obj.source();
1649             if (concealedPackages.contains(source)) {
1650                 throw new IllegalStateException("Package " + source
1651                                                 + " already declared");
1652             }
1653             if (opens.containsKey(source)) {
1654                 throw new IllegalStateException("Open package " + source
1655                                                 + " already declared");
1656             }
1657 
1658             opens.put(source, obj);

1659             return this;
1660         }
1661 
1662 
1663         /**
1664          * Adds an <em>opens</em> directive, with the given (and possibly empty)
1665          * set of modifiers, to open a package to a set of target modules.
1666          *
1667          * @param  ms
1668          *         The set of modifiers
1669          * @param  pn
1670          *         The package name
1671          * @param  targets
1672          *         The set of target modules names
1673          *
1674          * @return This builder
1675          *
1676          * @throws IllegalArgumentException
1677          *         If the package name or any of the target modules is {@code
1678          *         null} or is not a legal Java identifier, or the set of
1679          *         targets is empty

1680          * @throws IllegalStateException
1681          *         If the package is already declared as a package with the
1682          *         {@link #contains contains} method, the package is already
1683          *         declared as open, or this is a builder for an open module
1684          */
1685         public Builder opens(Set<Opens.Modifier> ms,
1686                              String pn,
1687                              Set<String> targets)
1688         {
1689             Opens e = new Opens(ms, requirePackageName(pn), targets);
1690 
1691             // check targets
1692             targets = e.targets();
1693             if (targets.isEmpty())
1694                 throw new IllegalArgumentException("Empty target set");
1695             if (strict)

1696                 targets.stream().forEach(Checks::requireModuleName);
1697 
1698             return opens(e);
1699         }
1700 
1701         /**
1702          * Adds an <em>opens</em> directive to open a package with the given (and
1703          * possibly empty) set of modifiers.
1704          *
1705          * @param  ms
1706          *         The set of modifiers
1707          * @param  pn
1708          *         The package name
1709          *
1710          * @return This builder
1711          *
1712          * @throws IllegalArgumentException
1713          *         If the package name is {@code null} or is not a legal Java
1714          *         identifier
1715          * @throws IllegalStateException
1716          *         If the package is already declared as a package with the
1717          *         {@link #contains contains} method, the package is already
1718          *         declared as open, or this is a builder for an open module
1719          */
1720         public Builder opens(Set<Opens.Modifier> ms, String pn) {
1721             Opens e = new Opens(ms, requirePackageName(pn), Collections.emptySet());



1722             return opens(e);
1723         }
1724 
1725         /**
1726          * Adds an <em>opens</em> directive to open a package to a set of target
1727          * modules.
1728          *
1729          * @param  pn
1730          *         The package name
1731          * @param  targets
1732          *         The set of target modules names
1733          *
1734          * @return This builder
1735          *
1736          * @throws IllegalArgumentException
1737          *         If the package name or any of the target modules is {@code
1738          *         null} or is not a legal Java identifier, or the set of
1739          *         targets is empty

1740          * @throws IllegalStateException
1741          *         If the package is already declared as a package with the
1742          *         {@link #contains contains} method, the package is already
1743          *         declared as open, or this is a builder for an open module
1744          */
1745         public Builder opens(String pn, Set<String> targets) {
1746             return opens(Collections.emptySet(), pn, targets);
1747         }
1748 
1749         /**
1750          * Adds an <em>opens</em> directive to open a package.
1751          *
1752          * @param  pn
1753          *         The package name
1754          *
1755          * @return This builder
1756          *
1757          * @throws IllegalArgumentException
1758          *         If the package name is {@code null} or is not a legal Java
1759          *         identifier
1760          * @throws IllegalStateException
1761          *         If the package is already declared as a package with the
1762          *         {@link #contains contains} method, the package is already
1763          *         declared as open, or this is a builder for an open module
1764          */
1765         public Builder opens(String pn) {
1766             return opens(Collections.emptySet(), pn);
1767         }
1768 
1769         /**
1770          * Adds a service dependence.
1771          *
1772          * @param  service
1773          *         The service type
1774          *
1775          * @return This builder
1776          *
1777          * @throws IllegalArgumentException
1778          *         If the service type is {@code null} or is not a legal Java
1779          *         identifier
1780          * @throws IllegalStateException
1781          *         If a dependency on the service type has already been declared

1782          */
1783         public Builder uses(String service) {



1784             if (uses.contains(requireServiceTypeName(service)))
1785                 throw new IllegalStateException("Dependence upon service "
1786                                                 + service + " already declared");
1787             uses.add(service);
1788             return this;
1789         }
1790 
1791         /**
1792          * Provides a service with one or more implementations.


1793          *
1794          * @param  p
1795          *         The provides
1796          *
1797          * @return This builder
1798          *
1799          * @throws IllegalStateException
1800          *         If the providers for the service type have already been
1801          *         declared
1802          */
1803         public Builder provides(Provides p) {
1804             String st = p.service();
1805             if (provides.containsKey(st))
1806                 throw new IllegalStateException("Providers of service "
1807                                                 + st + " already declared");
1808             provides.put(st, p);

1809             return this;
1810         }
1811 
1812         /**
1813          * Provides implementations of a service.

1814          *
1815          * @param  service
1816          *         The service type
1817          * @param  providers
1818          *         The list of provider or provider factory class names
1819          *
1820          * @return This builder
1821          *
1822          * @throws IllegalArgumentException
1823          *         If the service type or any of the provider class names is
1824          *         {@code null} or is not a legal Java identifier, or the list
1825          *         of provider class names is empty
1826          * @throws IllegalStateException
1827          *         If the providers for the service type have already been
1828          *         declared
1829          */
1830         public Builder provides(String service, List<String> providers) {
1831             if (provides.containsKey(service))
1832                 throw new IllegalStateException("Providers of service "
1833                                                 + service + " already declared by " + name);
1834 
1835             Provides p = new Provides(requireServiceTypeName(service), providers);
1836 
1837             // check providers after the set has been copied.
1838             List<String> providerNames = p.providers();
1839             if (providerNames.isEmpty())
1840                 throw new IllegalArgumentException("Empty providers set");


1841             providerNames.forEach(Checks::requireServiceProviderName);
1842             provides.put(service, p);
1843             return this;




1844         }
1845 
1846         /**
1847          * Provides an implementation of a service.
1848          *
1849          * @param  service
1850          *         The service type
1851          * @param  provider
1852          *         The provider or provider factory class name
1853          *
1854          * @return This builder
1855          *
1856          * @throws IllegalArgumentException
1857          *         If the service type or the provider class name is {@code
1858          *         null} or is not a legal Java identifier
1859          * @throws IllegalStateException
1860          *         If the providers for the service type have already been
1861          *         declared
1862          */
1863         public Builder provides(String service, String provider) {
1864             if (provider == null)
1865                 throw new IllegalArgumentException("'provider' is null");
1866             return provides(service, List.of(provider));
1867         }
1868 
1869         /**
1870          * Adds a (possible empty) set of packages to the module

1871          *
1872          * @param  pns
1873          *         The set of package names
1874          *
1875          * @return This builder
1876          *
1877          * @throws IllegalArgumentException
1878          *         If any of the package names is {@code null} or is not a
1879          *         legal Java identifier
1880          * @throws IllegalStateException
1881          *         If any of packages are already declared as packages in
1882          *         the module. This includes packages that are already
1883          *         declared as exported or open packages.
1884          */
1885         public Builder contains(Set<String> pns) {
1886             pns.forEach(this::contains);
1887             return this;
1888         }
1889 
1890         /**
1891          * Adds a package to the module.
1892          *
1893          * @param  pn
1894          *         The package name
1895          *
1896          * @return This builder
1897          *
1898          * @throws IllegalArgumentException
1899          *         If the package name is {@code null}, or is not a legal Java
1900          *         identifier
1901          * @throws IllegalStateException
1902          *         If the package is already declared as a package in the
1903          *         module. This includes the package already declared as an
1904          *         exported or open package.
1905          */
1906         public Builder contains(String pn) {
1907             Checks.requirePackageName(pn);
1908             if (concealedPackages.contains(pn)) {
1909                 throw new IllegalStateException("Package " + pn
1910                                                 + " already declared");
1911             }
1912             if (exports.containsKey(pn)) {
1913                 throw new IllegalStateException("Exported package "
1914                                                 + pn + " already declared");
1915             }
1916             if (opens.containsKey(pn)) {
1917                 throw new IllegalStateException("Open package "
1918                                                  + pn + " already declared");
1919             }
1920             concealedPackages.add(pn);
1921             return this;
1922         }
1923 
1924         /**
1925          * Sets the module version.
1926          *
1927          * @param  v
1928          *         The version
1929          *
1930          * @return This builder
1931          */
1932         public Builder version(Version v) {
1933             version = requireNonNull(v);
1934             return this;
1935         }
1936 
1937         /**
1938          * Sets the module version.
1939          *
1940          * @param  v
1941          *         The version string to parse
1942          *
1943          * @return This builder
1944          *
1945          * @throws IllegalArgumentException
1946          *         If {@code v} is null or cannot be parsed as a version string

1947          *
1948          * @see Version#parse(String)
1949          */
1950         public Builder version(String v) {
1951             return version(Version.parse(v));











1952         }
1953 
1954         /**
1955          * Sets the module main class.

1956          *
1957          * @param  mc
1958          *         The module main class
1959          *
1960          * @return This builder
1961          *
1962          * @throws IllegalArgumentException
1963          *         If {@code mainClass} is null or is not a legal Java identifier

1964          */
1965         public Builder mainClass(String mc) {
1966             mainClass = requireBinaryName("main class name", mc);













1967             return this;
1968         }
1969 
1970         /**
1971          * Sets the operating system name.
1972          *
1973          * @param  name
1974          *         The operating system name
1975          *
1976          * @return This builder
1977          *
1978          * @throws IllegalArgumentException
1979          *         If {@code name} is null or the empty String
1980          */
1981         public Builder osName(String name) {
1982             if (name == null || name.isEmpty())
1983                 throw new IllegalArgumentException("OS name is null or empty");
1984             osName = name;
1985             return this;
1986         }
1987 
1988         /**
1989          * Sets the operating system architecture.
1990          *
1991          * @param  arch
1992          *         The operating system architecture
1993          *
1994          * @return This builder
1995          *
1996          * @throws IllegalArgumentException
1997          *         If {@code name} is null or the empty String
1998          */
1999         public Builder osArch(String arch) {
2000             if (arch == null || arch.isEmpty())
2001                 throw new IllegalArgumentException("OS arch is null or empty");
2002             osArch = arch;
2003             return this;
2004         }
2005 
2006         /**
2007          * Sets the operating system version.
2008          *
2009          * @param  version
2010          *         The operating system version
2011          *
2012          * @return This builder
2013          *
2014          * @throws IllegalArgumentException
2015          *         If {@code name} is null or the empty String
2016          */
2017         public Builder osVersion(String version) {
2018             if (version == null || version.isEmpty())
2019                 throw new IllegalArgumentException("OS version is null or empty");
2020             osVersion = version;
2021             return this;
2022         }
2023 
2024         /**
2025          * Builds and returns a {@code ModuleDescriptor} from its components.
2026          *







2027          * @return The module descriptor
2028          */
2029         public ModuleDescriptor build() {
2030             Set<Requires> requires = new HashSet<>(this.requires.values());
2031 
2032             Set<String> packages = new HashSet<>();
2033             packages.addAll(exports.keySet());
2034             packages.addAll(opens.keySet());
2035             packages.addAll(concealedPackages);
2036 
2037             Set<Exports> exports = new HashSet<>(this.exports.values());
2038             Set<Opens> opens = new HashSet<>(this.opens.values());
2039 









2040             Set<Provides> provides = new HashSet<>(this.provides.values());
2041 
2042             return new ModuleDescriptor(name,
2043                                         version,
2044                                         open,
2045                                         automatic,
2046                                         synthetic,
2047                                         requires,
2048                                         exports,
2049                                         opens,
2050                                         uses,
2051                                         provides,
2052                                         packages,
2053                                         mainClass,
2054                                         osName,
2055                                         osArch,
2056                                         osVersion);
2057         }
2058 
2059     }
2060 
2061     /**
2062      * Compares this module descriptor to another.
2063      *
2064      * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
2065      * module name lexicographically.  Where the module names are equal then
2066      * the versions, if present, are compared. </p>
2067      *
2068      * @apiNote For now, the natural ordering is not consistent with equals.
2069      * If two module descriptors have equal module names, equal versions if
2070      * present, but their corresponding components are not equal, then they
2071      * will be considered equal by this method.




2072      *
2073      * @param  that
2074      *         The object to which this module descriptor is to be compared
2075      *
2076      * @return A negative integer, zero, or a positive integer if this module
2077      *         descriptor is less than, equal to, or greater than the given
2078      *         module descriptor
2079      */
2080     @Override
2081     public int compareTo(ModuleDescriptor that) {


2082         int c = this.name().compareTo(that.name());
2083         if (c != 0) return c;
2084         if (version == null) {
2085             if (that.version == null)





































2086                 return 0;
2087             return -1;
2088         }
2089         if (that.version == null)
2090             return +1;
2091         return version.compareTo(that.version);
2092     }
2093 
2094     /**
2095      * Tests this module descriptor for equality with the given object.
2096      *
2097      * <p> If the given object is not a {@code ModuleDescriptor} then this
2098      * method returns {@code false}. Two module descriptors are equal if each
2099      * of their corresponding components is equal. </p>
2100      *
2101      * <p> This method satisfies the general contract of the {@link
2102      * java.lang.Object#equals(Object) Object.equals} method. </p>
2103      *
2104      * @param   ob
2105      *          the object to which this object is to be compared
2106      *
2107      * @return  {@code true} if, and only if, the given object is a module
2108      *          descriptor that is equal to this module descriptor
2109      */
2110     @Override
2111     public boolean equals(Object ob) {
2112         if (ob == this)
2113             return true;
2114         if (!(ob instanceof ModuleDescriptor))
2115             return false;
2116         ModuleDescriptor that = (ModuleDescriptor)ob;
2117         return (name.equals(that.name)
2118                 && open == that.open
2119                 && automatic == that.automatic
2120                 && synthetic == that.synthetic
2121                 && requires.equals(that.requires)

2122                 && exports.equals(that.exports)
2123                 && opens.equals(that.opens)
2124                 && uses.equals(that.uses)
2125                 && provides.equals(that.provides)
2126                 && Objects.equals(version, that.version)
2127                 && Objects.equals(mainClass, that.mainClass)
2128                 && Objects.equals(osName, that.osName)
2129                 && Objects.equals(osArch, that.osArch)
2130                 && Objects.equals(osVersion, that.osVersion)
2131                 && Objects.equals(packages, that.packages));
2132     }
2133 
2134     private transient int hash;  // cached hash code
2135 
2136     /**
2137      * Computes a hash code for this module descriptor.
2138      *
2139      * <p> The hash code is based upon the components of the module descriptor,
2140      * and satisfies the general contract of the {@link Object#hashCode
2141      * Object.hashCode} method. </p>
2142      *
2143      * @return The hash-code value for this module descriptor
2144      */
2145     @Override
2146     public int hashCode() {
2147         int hc = hash;
2148         if (hc == 0) {
2149             hc = name.hashCode();
2150             hc = hc * 43 + Boolean.hashCode(open);
2151             hc = hc * 43 + Boolean.hashCode(automatic);
2152             hc = hc * 43 + Boolean.hashCode(synthetic);
2153             hc = hc * 43 + requires.hashCode();

2154             hc = hc * 43 + exports.hashCode();
2155             hc = hc * 43 + opens.hashCode();
2156             hc = hc * 43 + uses.hashCode();
2157             hc = hc * 43 + provides.hashCode();
2158             hc = hc * 43 + Objects.hashCode(version);
2159             hc = hc * 43 + Objects.hashCode(mainClass);
2160             hc = hc * 43 + Objects.hashCode(osName);
2161             hc = hc * 43 + Objects.hashCode(osArch);
2162             hc = hc * 43 + Objects.hashCode(osVersion);
2163             hc = hc * 43 + Objects.hashCode(packages);
2164             if (hc == 0)
2165                 hc = -1;
2166             hash = hc;
2167         }
2168         return hc;
2169     }

2170 
2171     /**
2172      * Returns a string describing this descriptor.
2173      *
2174      * @return A string describing this descriptor
2175      */
2176     @Override
2177     public String toString() {
2178         StringBuilder sb = new StringBuilder();
2179 
2180         if (isOpen())
2181             sb.append("open ");
2182         sb.append("module { name: ").append(toNameAndVersion());
2183         if (!requires.isEmpty())
2184             sb.append(", ").append(requires);
2185         if (!uses.isEmpty())
2186             sb.append(", uses: ").append(uses);
2187         if (!exports.isEmpty())
2188             sb.append(", exports: ").append(exports);
2189         if (!opens.isEmpty())
2190             sb.append(", opens: ").append(opens);
2191         if (!provides.isEmpty()) {
2192             sb.append(", provides: ").append(provides);
2193         }
2194         sb.append(" }");
2195         return sb.toString();
2196     }
2197 
2198 
2199     /**
2200      * Instantiates a builder to build a module descriptor.
2201      *
2202      * @param  name
2203      *         The module name






















2204      *
2205      * @return A new builder
2206      *
2207      * @throws IllegalArgumentException
2208      *         If the module name is {@code null} or is not a legal Java
2209      *         identifier
2210      */
2211     public static Builder module(String name) {
2212         return new Builder(name, true, false, false);
2213     }
2214 
2215     /**
2216      * Instantiates a builder to build a module descriptor for an open module.
2217      * An open module does not declare any open packages but the resulting
2218      * module is treated as if all packages are open.
2219      *
2220      * <p> As an example, the following creates a module descriptor for an open
2221      * name "{@code m}" containing two packages, one of which is exported. </p>
2222      * <pre>{@code
2223      *     ModuleDescriptor descriptor = ModuleDescriptor.openModule("m")
2224      *         .requires("java.base")
2225      *         .exports("p")
2226      *         .contains("q")
2227      *         .build();
2228      * }</pre>
2229      *
2230      * @param  name
2231      *         The module name
2232      *
2233      * @return A new builder that builds an open module
2234      *
2235      * @throws IllegalArgumentException
2236      *         If the module name is {@code null} or is not a legal Java
2237      *         identifier
2238      */
2239     public static Builder openModule(String name) {
2240         return new Builder(name, true, true, false);
2241     }
2242 
2243     /**
2244      * Instantiates a builder to build a module descriptor for an automatic
2245      * module. Automatic modules receive special treatment during resolution
2246      * (see {@link Configuration}) so that they read all other modules. When
2247      * Instantiated in the Java virtual machine as a {@link java.lang.reflect.Module}
2248      * then the Module reads every unnamed module in the Java virtual machine.

2249      *
2250      * @param  name
2251      *         The module name
2252      *
2253      * @return A new builder that builds an automatic module
2254      *
2255      * @throws IllegalArgumentException
2256      *         If the module name is {@code null} or is not a legal Java
2257      *         identifier
2258      *
2259      * @see ModuleFinder#of(Path[])
2260      */
2261     public static Builder automaticModule(String name) {
2262         return new Builder(name, true, false, false).automatic(true);
2263     }
2264 
2265 
2266     /**
2267      * Reads the binary form of a module declaration from an input stream
2268      * as a module descriptor.
2269      *
2270      * <p> If the descriptor encoded in the input stream does not indicate a
2271      * set of packages in the module then the {@code packageFinder} will be
2272      * invoked. If the {@code packageFinder} throws an {@link UncheckedIOException}
2273      * then {@link IOException} cause will be re-thrown. </p>




2274      *
2275      * <p> If there are bytes following the module descriptor then it is
2276      * implementation specific as to whether those bytes are read, ignored,
2277      * or reported as an {@code InvalidModuleDescriptorException}. If this
2278      * method fails with an {@code InvalidModuleDescriptorException} or {@code
2279      * IOException} then it may do so after some, but not all, bytes have
2280      * been read from the input stream. It is strongly recommended that the
2281      * stream be promptly closed and discarded if an exception occurs. </p>
2282      *
2283      * @apiNote The {@code packageFinder} parameter is for use when reading
2284      * module descriptors from legacy module-artifact formats that do not
2285      * record the set of packages in the descriptor itself.
2286      *
2287      * @param  in
2288      *         The input stream
2289      * @param  packageFinder
2290      *         A supplier that can produce the set of packages
2291      *
2292      * @return The module descriptor
2293      *
2294      * @throws InvalidModuleDescriptorException
2295      *         If an invalid module descriptor is detected


2296      * @throws IOException
2297      *         If an I/O error occurs reading from the input stream or {@code
2298      *         UncheckedIOException} is thrown by the package finder
2299      */
2300     public static ModuleDescriptor read(InputStream in,
2301                                         Supplier<Set<String>> packageFinder)
2302         throws IOException
2303     {
2304         return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
2305     }
2306 
2307     /**
2308      * Reads the binary form of a module declaration from an input stream
2309      * as a module descriptor.




2310      *
2311      * @param  in
2312      *         The input stream
2313      *
2314      * @return The module descriptor
2315      *
2316      * @throws InvalidModuleDescriptorException
2317      *         If an invalid module descriptor is detected
2318      * @throws IOException
2319      *         If an I/O error occurs reading from the input stream
2320      */
2321     public static ModuleDescriptor read(InputStream in) throws IOException {
2322         return ModuleInfo.read(in, null).descriptor();
2323     }
2324 
2325     /**
2326      * Reads the binary form of a module declaration from a byte buffer
2327      * as a module descriptor.
2328      *
2329      * <p> If the descriptor encoded in the byte buffer does not indicate a
2330      * set of packages then the {@code packageFinder} will be invoked. </p>






2331      *
2332      * <p> The module descriptor is read from the buffer stating at index
2333      * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
2334      * position} when this method is invoked. Upon return the buffer's position
2335      * will be equal to {@code p + n} where {@code n} is the number of bytes
2336      * read from the buffer. </p>
2337      *
2338      * <p> If there are bytes following the module descriptor then it is
2339      * implementation specific as to whether those bytes are read, ignored,
2340      * or reported as an {@code InvalidModuleDescriptorException}. If this
2341      * method fails with an {@code InvalidModuleDescriptorException} then it
2342      * may do so after some, but not all, bytes have been read. </p>
2343      *
2344      * @apiNote The {@code packageFinder} parameter is for use when reading
2345      * module descriptors from legacy module-artifact formats that do not
2346      * record the set of packages in the descriptor itself.
2347      *
2348      * @param  bb
2349      *         The byte buffer
2350      * @param  packageFinder
2351      *         A supplier that can produce the set of packages
2352      *
2353      * @return The module descriptor
2354      *
2355      * @throws InvalidModuleDescriptorException
2356      *         If an invalid module descriptor is detected


2357      */
2358     public static ModuleDescriptor read(ByteBuffer bb,
2359                                         Supplier<Set<String>> packageFinder)
2360     {
2361         return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
2362     }
2363 
2364     /**
2365      * Reads the binary form of a module declaration from a byte buffer
2366      * as a module descriptor.



2367      *
2368      * @param  bb
2369      *         The byte buffer
2370      *
2371      * @return The module descriptor
2372      *
2373      * @throws InvalidModuleDescriptorException
2374      *         If an invalid module descriptor is detected
2375      */
2376     public static ModuleDescriptor read(ByteBuffer bb) {
2377         return ModuleInfo.read(bb, null).descriptor();
2378     }
2379 
2380     private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
2381         if (map.isEmpty()) {
2382             return Collections.emptyMap();
2383         } else if (map.size() == 1) {
2384             Map.Entry<K, V> entry = map.entrySet().iterator().next();
2385             return Collections.singletonMap(entry.getKey(), entry.getValue());
2386         } else {
2387             return Collections.unmodifiableMap(map);
2388         }
2389     }
2390 
2391     private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) {
2392         if (set.isEmpty()) {
2393             return Collections.emptySet();
2394         } else if (set.size() == 1) {
2395             return Collections.singleton(set.iterator().next());
2396         } else {
2397             return Collections.unmodifiableSet(set);
2398         }
2399     }
2400 





2401     /**
2402      * Returns a string containing the given set of modifiers and label.
2403      */
2404     private static <M> String toString(Set<M> mods, String what) {
2405         return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
2406                               Stream.of(what)))
2407                 .collect(Collectors.joining(" "));
2408     }
2409 








































2410     static {
2411         /**
2412          * Setup the shared secret to allow code in other packages access
2413          * private package methods in java.lang.module.
2414          */
2415         jdk.internal.misc.SharedSecrets
2416             .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
2417                 @Override
2418                 public Builder newModuleBuilder(String mn,
2419                                                 boolean strict,
2420                                                 boolean open,
2421                                                 boolean synthetic) {
2422                     return new Builder(mn, strict, open, synthetic);
2423                 }
2424 
2425                 @Override
2426                 public Set<String> exportedPackages(ModuleDescriptor.Builder builder) {
2427                     return builder.exportedPackages();
2428                 }
2429 
2430                 @Override
2431                 public Set<String> openPackages(ModuleDescriptor.Builder builder) {
2432                     return builder.openPackages();



2433                 }
2434 
2435                 @Override
2436                 public Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v) {
2437                     return new Requires(ms, mn, v, true);
2438                 }
2439 
2440                 @Override
2441                 public Exports newExports(Set<Exports.Modifier> ms, String source) {
2442                     return new Exports(ms, source, Collections.emptySet(), true);
2443                 }
2444 
2445                 @Override
2446                 public Exports newExports(Set<Exports.Modifier> ms,
2447                                           String source,
2448                                           Set<String> targets) {
2449                     return new Exports(ms, source, targets, true);
2450                 }
2451 
2452                 @Override
2453                 public Opens newOpens(Set<Opens.Modifier> ms,
2454                                       String source,
2455                                       Set<String> targets) {
2456                     return new Opens(ms, source, targets, true);
2457                 }
2458 
2459                 @Override
2460                 public Opens newOpens(Set<Opens.Modifier> ms, String source) {
2461                     return new Opens(ms, source, Collections.emptySet(), true);
2462                 }
2463 
2464                 @Override
2465                 public Provides newProvides(String service, List<String> providers) {
2466                     return new Provides(service, providers, true);
2467                 }
2468 
2469                 @Override
2470                 public Version newVersion(String v) {
2471                     return new Version(v);
2472                 }
2473 
2474                 @Override
2475                 public ModuleDescriptor newModuleDescriptor(ModuleDescriptor md,
2476                                                             Set<String> pkgs) {
2477                     return new ModuleDescriptor(md, pkgs);
2478                 }
2479 
2480                 @Override
2481                 public ModuleDescriptor newModuleDescriptor(String name,
2482                                                             Version version,
2483                                                             boolean open,
2484                                                             boolean automatic,
2485                                                             boolean synthetic,
2486                                                             Set<Requires> requires,
2487                                                             Set<Exports> exports,
2488                                                             Set<Opens> opens,
2489                                                             Set<String> uses,
2490                                                             Set<Provides> provides,
2491                                                             Set<String> packages,
2492                                                             String mainClass,
2493                                                             String osName,
2494                                                             String osArch,
2495                                                             String osVersion,
2496                                                             int hashCode) {
2497                     return new ModuleDescriptor(name,
2498                                                 version,
2499                                                 open,
2500                                                 automatic,
2501                                                 synthetic,
2502                                                 requires,
2503                                                 exports,
2504                                                 opens,
2505                                                 uses,
2506                                                 provides,
2507                                                 packages,
2508                                                 mainClass,
2509                                                 osName,
2510                                                 osArch,
2511                                                 osVersion,
2512                                                 hashCode,
2513                                                 false);
2514                 }
2515 
2516                 @Override
2517                 public Configuration resolveRequiresAndUses(ModuleFinder finder,
2518                                                             Collection<String> roots,
2519                                                             boolean check,
2520                                                             PrintStream traceOutput)
2521                 {
2522                     return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
2523                 }
2524             });
2525     }
2526 
2527 }
   1 /*
   2  * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.module;
  27 
  28 import java.io.InputStream;
  29 import java.io.IOException;
  30 import java.io.PrintStream;
  31 import java.io.UncheckedIOException;
  32 import java.nio.ByteBuffer;
  33 import java.nio.file.Path;
  34 import java.util.ArrayList;
  35 import java.util.Collection;
  36 import java.util.Collections;
  37 import java.util.EnumSet;
  38 import java.util.HashMap;
  39 import java.util.HashSet;
  40 import java.util.Iterator;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.Objects;
  44 import java.util.Optional;
  45 import java.util.Set;
  46 import java.util.TreeSet;
  47 import java.util.function.Supplier;
  48 import java.util.stream.Collectors;
  49 import java.util.stream.Stream;
  50 
  51 import static jdk.internal.module.Checks.*;
  52 import static java.util.Objects.*;
  53 
  54 import jdk.internal.module.Checks;
  55 import jdk.internal.module.ModuleInfo;
  56 
  57 
  58 /**
  59  * A module descriptor.
  60  *
  61  * <p> A module descriptor describes a named module and defines methods to
  62  * obtain each of its components. The module descriptor for a named module
  63  * in the Java virtual machine is obtained by invoking the {@link
  64  * java.lang.reflect.Module Module}'s {@link java.lang.reflect.Module#getDescriptor
  65  * getDescriptor} method. Module descriptors can also be created using the
  66  * {@link ModuleDescriptor.Builder} class or by reading the binary form of a
  67  * module declaration ({@code module-info.class}) using the {@link
  68  * #read(InputStream,Supplier) read} methods defined here. </p>
  69  *
  70  * <p> A module descriptor describes a <em>normal</em>, open, or automatic
  71  * module. <em>Normal</em> modules and open modules describe their {@link
  72  * #requires() dependences}, {@link #exports() exported-packages}, the services
  73  * that they {@link #uses() use} or {@link #provides() provide}, and other
  74  * components. <em>Normal</em> modules may {@link #opens() open} specific
  75  * packages. The module descriptor for an open modules does not declare any
  76  * open packages (its {@code opens} method returns an empty set) but when
  77  * instantiated in the Java virtual machine then it is treated as if all
  78  * packages are open. The module descriptor for an automatic module does not
  79  * declare any dependences (except for the mandatory dependency on {@code
  80  * java.base}), and does not declare any exported or open packages. Automatic
  81  * module receive special treatment during resolution so that they read all
  82  * other modules in the configuration. When an automatic module is instantiated
  83  * in the Java virtual machine then it reads every unnamed module and is
  84  * treated as if all packages are exported and open. </p>
  85  *
  86  * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
  87  * multiple concurrent threads.</p>
  88  *

  89  * @see java.lang.reflect.Module
  90  * @since 9
  91  * @spec JPMS
  92  */
  93 
  94 public class ModuleDescriptor
  95     implements Comparable<ModuleDescriptor>
  96 {
  97 
  98     /**
  99      * A modifier on a module.
 100      *
 101      * @see ModuleDescriptor#modifiers()
 102      * @since 9
 103      */
 104     public static enum Modifier {
 105         /**
 106          * An open module. An open module does not declare any open packages
 107          * but the resulting module is treated as if all packages are open.
 108          */
 109         OPEN,
 110 
 111         /**
 112          * An automatic module. An automatic module is treated as if it exports
 113          * and opens all packages.
 114          *
 115          * @apiNote This modifier does not correspond to a module flag in the
 116          * binary form of a module declaration ({@code module-info.class}).
 117          */
 118         AUTOMATIC,
 119 
 120         /**
 121          * The module was not explicitly or implicitly declared.
 122          */
 123         SYNTHETIC,
 124 
 125         /**
 126          * The module was implicitly declared.
 127          */
 128         MANDATED;
 129     }
 130 
 131 
 132     /**
 133      * <p> A dependence upon a module </p>
 134      *
 135      * @see ModuleDescriptor#requires()
 136      * @since 9
 137      * @spec JPMS
 138      */
 139 
 140     public final static class Requires
 141         implements Comparable<Requires>
 142     {
 143 
 144         /**
 145          * A modifier on a module dependence.
 146          *
 147          * @see Requires#modifiers()
 148          * @since 9
 149          * @spec JPMS
 150          */
 151         public static enum Modifier {
 152 
 153             /**
 154              * The dependence causes any module which depends on the <i>current
 155              * module</i> to have an implicitly declared dependence on the module
 156              * named by the {@code Requires}.
 157              */
 158             TRANSITIVE,
 159 
 160             /**
 161              * The dependence is mandatory in the static phase, during compilation,
 162              * but is optional in the dynamic phase, during execution.
 163              */
 164             STATIC,
 165 
 166             /**
 167              * The dependence was not explicitly or implicitly declared in the
 168              * source of the module declaration.
 169              */


 212          *
 213          * @return The module name
 214          */
 215         public String name() {
 216             return name;
 217         }
 218 
 219         /**
 220          * Returns the version of the module if recorded at compile-time.
 221          *
 222          * @return The version of the module if recorded at compile-time
 223          */
 224         public Optional<Version> compiledVersion() {
 225             return Optional.ofNullable(compiledVersion);
 226         }
 227 
 228         /**
 229          * Compares this module dependence to another.
 230          *
 231          * <p> Two {@code Requires} objects are compared by comparing their
 232          * module names lexicographically. Where the module names are equal
 233          * then the sets of modifiers are compared in the same way that
 234          * module modifiers are compared (see {@link ModuleDescriptor#compareTo
 235          * ModuleDescriptor.compareTo}). Where the module names are equal and
 236          * the set of modifiers are equal then the version of the modules
 237          * recorded at compile-time are compared. When comparing the versions
 238          * recorded at compile-time then a dependence that has a recorded
 239          * version is considered to succeed a dependence that does not have a
 240          * recorded version. </p>
 241          *
 242          * @param  that
 243          *         The module dependence to compare
 244          *
 245          * @return A negative integer, zero, or a positive integer if this module
 246          *         dependence is less than, equal to, or greater than the given
 247          *         module dependence
 248          */
 249         @Override
 250         public int compareTo(Requires that) {
 251             if (this == that) return 0;
 252 
 253             int c = this.name().compareTo(that.name());
 254             if (c != 0) return c;

 255 
 256             // modifiers
 257             long v1 = modsValue(this.modifiers());
 258             long v2 = modsValue(that.modifiers());
 259             c = Long.compare(v1, v2);
 260             if (c != 0) return c;
 261 
 262             // compiledVersion
 263             c = compare(this.compiledVersion, that.compiledVersion);
 264             if (c != 0) return c;










 265 
 266             return 0;









 267         }
 268 
 269         /**
 270          * Tests this module dependence for equality with the given object.
 271          *
 272          * <p> If the given object is not a {@code Requires} then this method
 273          * returns {@code false}. Two module dependence objects are equal if
 274          * the module names are equal, set of modifiers are equal, and the
 275          * compiled version of both modules is equal or not recorded for
 276          * both modules. </p>
 277          *
 278          * <p> This method satisfies the general contract of the {@link
 279          * java.lang.Object#equals(Object) Object.equals} method. </p>
 280          *
 281          * @param   ob
 282          *          the object to which this object is to be compared
 283          *
 284          * @return  {@code true} if, and only if, the given object is a module
 285          *          dependence that is equal to this module dependence
 286          */


 294         }
 295 
 296         /**
 297          * Computes a hash code for this module dependence.
 298          *
 299          * <p> The hash code is based upon the module name, modifiers, and the
 300          * module version if recorded at compile time. It satisfies the general
 301          * contract of the {@link Object#hashCode Object.hashCode} method. </p>
 302          *
 303          * @return The hash-code value for this module dependence
 304          */
 305         @Override
 306         public int hashCode() {
 307             int hash = name.hashCode() * 43 + mods.hashCode();
 308             if (compiledVersion != null)
 309                 hash = hash * 43 + compiledVersion.hashCode();
 310             return hash;
 311         }
 312 
 313         /**
 314          * Returns a string describing this module dependence.
 315          *
 316          * @return A string describing this module dependence
 317          */
 318         @Override
 319         public String toString() {
 320             String what;
 321             if (compiledVersion != null) {
 322                 what = name() + " (@" + compiledVersion + ")";
 323             } else {
 324                 what = name();
 325             }
 326             return ModuleDescriptor.toString(mods, what);
 327         }
 328     }
 329 
 330 
 331 
 332     /**
 333      * <p> A package exported by a module, may be qualified or unqualified. </p>
 334      *
 335      * @see ModuleDescriptor#exports()
 336      * @since 9
 337      * @spec JPMS
 338      */
 339 
 340     public final static class Exports
 341         implements Comparable<Exports>
 342     {
 343 
 344         /**
 345          * A modifier on an exported package.
 346          *
 347          * @see Exports#modifiers()
 348          * @since 9
 349          * @spec JPMS
 350          */
 351         public static enum Modifier {
 352 
 353             /**
 354              * The export was not explicitly or implicitly declared in the
 355              * source of the module declaration.
 356              */
 357             SYNTHETIC,
 358 
 359             /**
 360              * The export was implicitly declared in the source of the module
 361              * declaration.
 362              */
 363             MANDATED;
 364 
 365         }
 366 
 367         private final Set<Modifier> mods;
 368         private final String source;
 369         private final Set<String> targets;  // empty if unqualified export


 414          *
 415          * @return The package name
 416          */
 417         public String source() {
 418             return source;
 419         }
 420 
 421         /**
 422          * For a qualified export, returns the non-empty and immutable set
 423          * of the module names to which the package is exported. For an
 424          * unqualified export, returns an empty set.
 425          *
 426          * @return The set of target module names or for an unqualified
 427          *         export, an empty set
 428          */
 429         public Set<String> targets() {
 430             return targets;
 431         }
 432 
 433         /**
 434          * Compares this module export to another.
 435          *
 436          * <p> Two {@code Exports} objects are compared by comparing the package
 437          * names lexicographically. Where the packages names are equal then the
 438          * sets of modifiers are compared in the same way that module modifiers
 439          * are compared (see {@link ModuleDescriptor#compareTo
 440          * ModuleDescriptor.compareTo}). Where the package names are equal and
 441          * the set of modifiers are equal then the set of target modules are
 442          * compared. This is done by sorting the sets, iterating over both sets
 443          * in ascending order, and comparing the corresponding elements
 444          * lexicographically. Where the sets differ in size, and the larger set
 445          * contains all elements of the smaller set, then the larger set is
 446          * considered to succeed the smaller set. </p>
 447          *
 448          * @param  that
 449          *         The module export to compare
 450          *
 451          * @return A negative integer, zero, or a positive integer if this module
 452          *         export is less than, equal to, or greater than the given
 453          *         export dependence
 454          */
 455         @Override
 456         public int compareTo(Exports that) {
 457             if (this == that) return 0;
 458 
 459             int c = source.compareTo(that.source);
 460             if (c != 0)
 461                 return c;
 462 
 463             // modifiers
 464             long v1 = modsValue(this.modifiers());
 465             long v2 = modsValue(that.modifiers());
 466             c = Long.compare(v1, v2);
 467             if (c != 0)
 468                 return c;
 469 
 470             // targets
 471             c = compare(targets, that.targets);
 472             if (c != 0)
 473                 return c;
 474 
 475             return 0;
 476         }
 477 
 478         /**
 479          * Computes a hash code for this module export.
 480          *
 481          * <p> The hash code is based upon the modifiers, the package name,
 482          * and for a qualified export, the set of modules names to which the
 483          * package is exported. It satisfies the general contract of the
 484          * {@link Object#hashCode Object.hashCode} method.
 485          *
 486          * @return The hash-code value for this module export
 487          */
 488         @Override
 489         public int hashCode() {
 490             int hash = mods.hashCode();
 491             hash = hash * 43 + source.hashCode();
 492             return hash * 43 + targets.hashCode();
 493         }
 494 
 495         /**
 496          * Tests this module export for equality with the given object.
 497          *
 498          * <p> If the given object is not an {@code Exports} then this method


 503          * <p> This method satisfies the general contract of the {@link
 504          * java.lang.Object#equals(Object) Object.equals} method. </p>
 505          *
 506          * @param   ob
 507          *          the object to which this object is to be compared
 508          *
 509          * @return  {@code true} if, and only if, the given object is a module
 510          *          dependence that is equal to this module dependence
 511          */
 512         @Override
 513         public boolean equals(Object ob) {
 514             if (!(ob instanceof Exports))
 515                 return false;
 516             Exports other = (Exports)ob;
 517             return Objects.equals(this.mods, other.mods)
 518                     && Objects.equals(this.source, other.source)
 519                     && Objects.equals(this.targets, other.targets);
 520         }
 521 
 522         /**
 523          * Returns a string describing the exported package.
 524          *
 525          * @return A string describing the exported package
 526          */
 527         @Override
 528         public String toString() {
 529             String s = ModuleDescriptor.toString(mods, source);
 530             if (targets.isEmpty())
 531                 return s;
 532             else
 533                 return s + " to " + targets;
 534         }
 535     }
 536 
 537 
 538     /**
 539      * <p> A package opened by a module, may be qualified or unqualified. </p>

 540      *
 541      * <p> The <em>opens</em> directive in a module declaration declares a
 542      * package to be open to allow all types in the package, and all their
 543      * members, not just public types and their public members to be reflected
 544      * on by APIs that support private access or a way to bypass or suppress
 545      * default Java language access control checks. </p>
 546      *
 547      * @see ModuleDescriptor#opens()
 548      * @since 9
 549      * @spec JPMS
 550      */
 551 
 552     public final static class Opens
 553         implements Comparable<Opens>
 554     {
 555         /**
 556          * A modifier on an open package.
 557          *
 558          * @see Opens#modifiers()
 559          * @since 9
 560          * @spec JPMS
 561          */
 562         public static enum Modifier {
 563 
 564             /**
 565              * The open package was not explicitly or implicitly declared in
 566              * the source of the module declaration.
 567              */
 568             SYNTHETIC,
 569 
 570             /**
 571              * The open package was implicitly declared in the source of the
 572              * module declaration.
 573              */
 574             MANDATED;
 575 
 576         }
 577 
 578         private final Set<Modifier> mods;
 579         private final String source;
 580         private final Set<String> targets;  // empty if unqualified export
 581 
 582         /**
 583          * Constructs an Opens
 584          */
 585         private Opens(Set<Modifier> ms, String source, Set<String> targets) {
 586             if (ms.isEmpty()) {
 587                 ms = Collections.emptySet();
 588             } else {
 589                 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
 590             }
 591             this.mods = ms;
 592             this.source = source;


 625          *
 626          * @return The package name
 627          */
 628         public String source() {
 629             return source;
 630         }
 631 
 632         /**
 633          * For a qualified opens, returns the non-empty and immutable set
 634          * of the module names to which the package is open. For an
 635          * unqualified opens, returns an empty set.
 636          *
 637          * @return The set of target module names or for an unqualified
 638          *         opens, an empty set
 639          */
 640         public Set<String> targets() {
 641             return targets;
 642         }
 643 
 644         /**
 645          * Compares this module opens to another.
 646          *
 647          * <p> Two {@code Opens} objects are compared by comparing the package
 648          * names lexicographically. Where the packages names are equal then the
 649          * sets of modifiers are compared in the same way that module modifiers
 650          * are compared (see {@link ModuleDescriptor#compareTo
 651          * ModuleDescriptor.compareTo}). Where the package names are equal and
 652          * the set of modifiers are equal then the set of target modules are
 653          * compared. This is done by sorting the sets, iterating over both sets
 654          * in ascending order, and comparing the corresponding elements
 655          * lexicographically. Where the sets differ in size, and the larger set
 656          * contains all elements of the smaller set, then the larger set is
 657          * considered to succeed the smaller set. </p>
 658          *
 659          * @param  that
 660          *         The module opens to compare
 661          *
 662          * @return A negative integer, zero, or a positive integer if this module
 663          *         opens is less than, equal to, or greater than the given
 664          *         module opens
 665          */
 666         @Override
 667         public int compareTo(Opens that) {
 668             if (this == that) return 0;
 669 
 670             int c = source.compareTo(that.source);
 671             if (c != 0)
 672                 return c;
 673 
 674             // modifiers
 675             long v1 = modsValue(this.modifiers());
 676             long v2 = modsValue(that.modifiers());
 677             c = Long.compare(v1, v2);
 678             if (c != 0)
 679                 return c;
 680 
 681             // targets
 682             c = compare(targets, that.targets);
 683             if (c != 0)
 684                 return c;
 685 
 686             return 0;
 687         }
 688 
 689         /**
 690          * Computes a hash code for this module opens.
 691          *
 692          * <p> The hash code is based upon the modifiers, the package name,
 693          * and for a qualified opens, the set of modules names to which the
 694          * package is opened. It satisfies the general contract of the
 695          * {@link Object#hashCode Object.hashCode} method.
 696          *
 697          * @return The hash-code value for this module opens
 698          */
 699         @Override
 700         public int hashCode() {
 701             int hash = mods.hashCode();
 702             hash = hash * 43 + source.hashCode();
 703             return hash * 43 + targets.hashCode();
 704         }
 705 
 706         /**
 707          * Tests this module opens for equality with the given object.
 708          *
 709          * <p> If the given object is not an {@code Opens} then this method


 714          * <p> This method satisfies the general contract of the {@link
 715          * java.lang.Object#equals(Object) Object.equals} method. </p>
 716          *
 717          * @param   ob
 718          *          the object to which this object is to be compared
 719          *
 720          * @return  {@code true} if, and only if, the given object is a module
 721          *          dependence that is equal to this module dependence
 722          */
 723         @Override
 724         public boolean equals(Object ob) {
 725             if (!(ob instanceof Opens))
 726                 return false;
 727             Opens other = (Opens)ob;
 728             return Objects.equals(this.mods, other.mods)
 729                     && Objects.equals(this.source, other.source)
 730                     && Objects.equals(this.targets, other.targets);
 731         }
 732 
 733         /**
 734          * Returns a string describing the open package.
 735          *
 736          * @return A string describing the open package
 737          */
 738         @Override
 739         public String toString() {
 740             String s = ModuleDescriptor.toString(mods, source);
 741             if (targets.isEmpty())
 742                 return s;
 743             else
 744                 return s + " to " + targets;
 745         }
 746     }
 747 
 748 
 749     /**
 750      * <p> A service that a module provides one or more implementations of. </p>
 751      *
 752      * @see ModuleDescriptor#provides()
 753      * @since 9
 754      * @spec JPMS
 755      */
 756 
 757     public final static class Provides
 758         implements Comparable<Provides>
 759     {
 760         private final String service;
 761         private final List<String> providers;
 762 
 763         private Provides(String service, List<String> providers) {
 764             this.service = service;
 765             this.providers = Collections.unmodifiableList(providers);
 766         }
 767 
 768         private Provides(String service, List<String> providers, boolean unused) {
 769             this.service = service;
 770             this.providers = providers;
 771         }
 772 
 773         /**
 774          * Returns the fully qualified class name of the service type.
 775          *
 776          * @return The fully qualified class name of the service type.
 777          */
 778         public String service() { return service; }
 779 
 780         /**
 781          * Returns the list of the fully qualified class names of the providers
 782          * or provider factories.
 783          *
 784          * @return A non-empty and unmodifiable list of the fully qualified class
 785          *         names of the providers or provider factories
 786          */
 787         public List<String> providers() { return providers; }
 788 
 789         /**
 790          * Compares this provides to another.
 791          *
 792          * <p> Two {@code Provides} objects are compared by comparing the fully
 793          * qualified class name of the service type lexicographically. Where the
 794          * class names are equal then the list of the provider class names are
 795          * compared by comparing the corresponding elements of both lists
 796          * lexicographically and in sequence. Where the lists differ in size,
 797          * {@code N} is the size of the shorter list, and the first {@code N}
 798          * corresponding elements are equal, then the longer list is considered
 799          * to succeed the shorter list. </p>
 800          *
 801          * @param  that
 802          *         The {@code Provides} to compare
 803          *
 804          * @return A negative integer, zero, or a positive integer if this provides
 805          *         is less than, equal to, or greater than the given provides
 806          */
 807         public int compareTo(Provides that) {
 808             if (this == that) return 0;
 809 
 810             int c = service.compareTo(that.service);
 811             if (c != 0) return c;
 812 
 813             // compare provider class names in sequence
 814             int size1 = this.providers.size();
 815             int size2 = that.providers.size();
 816             for (int index=0; index<Math.min(size1, size2); index++) {
 817                 String e1 = this.providers.get(index);
 818                 String e2 = that.providers.get(index);
 819                 c = e1.compareTo(e2);
 820                 if (c != 0) return c;
 821             }
 822             if (size1 == size2) {
 823                 return 0;
 824             } else {
 825                 return (size1 > size2) ? 1 : -1;
 826             }
 827         }
 828 
 829         /**
 830          * Computes a hash code for this provides.
 831          *
 832          * <p> The hash code is based upon the service type and the set of
 833          * providers. It satisfies the general contract of the {@link
 834          * Object#hashCode Object.hashCode} method. </p>
 835          *
 836          * @return The hash-code value for this module provides
 837          */
 838         @Override
 839         public int hashCode() {
 840             return service.hashCode() * 43 + providers.hashCode();
 841         }
 842 
 843         /**
 844          * Tests this provides for equality with the given object.
 845          *
 846          * <p> If the given object is not a {@code Provides} then this method
 847          * returns {@code false}. Two {@code Provides} objects are equal if the
 848          * service type is equal and the list of providers is equal. </p>
 849          *


 867 
 868         /**
 869          * Returns a string describing this provides.
 870          *
 871          * @return A string describing this provides
 872          */
 873         @Override
 874         public String toString() {
 875             return service + " with " + providers;
 876         }
 877 
 878     }
 879 
 880 
 881 
 882     /**
 883      * A module's version string.
 884      *
 885      * <p> A version string has three components: The version number itself, an
 886      * optional pre-release version, and an optional build version.  Each
 887      * component is a sequence of tokens; each token is either a non-negative
 888      * integer or a string.  Tokens are separated by the punctuation characters
 889      * {@code '.'}, {@code '-'}, or {@code '+'}, or by transitions from a
 890      * sequence of digits to a sequence of characters that are neither digits
 891      * nor punctuation characters, or vice versa.
 892      *
 893      * <ul>
 894      *
 895      *   <li> The <i>version number</i> is a sequence of tokens separated by
 896      *   {@code '.'} characters, terminated by the first {@code '-'} or {@code
 897      *   '+'} character. </li>
 898      *
 899      *   <li> The <i>pre-release version</i> is a sequence of tokens separated
 900      *   by {@code '.'} or {@code '-'} characters, terminated by the first
 901      *   {@code '+'} character. </li>
 902      *
 903      *   <li> The <i>build version</i> is a sequence of tokens separated by
 904      *   {@code '.'}, {@code '-'}, or {@code '+'} characters.
 905      *
 906      * </ul>
 907      *
 908      * <p> When comparing two version strings, the elements of their
 909      * corresponding components are compared in pointwise fashion.  If one
 910      * component is longer than the other, but otherwise equal to it, then the
 911      * first component is considered the greater of the two; otherwise, if two
 912      * corresponding elements are integers then they are compared as such;
 913      * otherwise, at least one of the elements is a string, so the other is
 914      * converted into a string if it is an integer and the two are compared
 915      * lexicographically.  Trailing integer elements with the value zero are
 916      * ignored.
 917      *
 918      * <p> Given two version strings, if their version numbers differ then the
 919      * result of comparing them is the result of comparing their version
 920      * numbers; otherwise, if one of them has a pre-release version but the
 921      * other does not then the first is considered to precede the second,
 922      * otherwise the result of comparing them is the result of comparing their
 923      * pre-release versions; otherwise, the result of comparing them is the
 924      * result of comparing their build versions.
 925      *
 926      * @see ModuleDescriptor#version()
 927      * @since 9
 928      * @spec JPMS
 929      */
 930 
 931     public final static class Version
 932         implements Comparable<Version>
 933     {
 934 
 935         private final String version;
 936 
 937         // If Java had disjunctive types then we'd write List<Integer|String> here
 938         //
 939         private final List<Object> sequence;
 940         private final List<Object> pre;
 941         private final List<Object> build;
 942 
 943         // Take a numeric token starting at position i
 944         // Append it to the given list
 945         // Return the index of the first character not taken
 946         // Requires: s.charAt(i) is (decimal) numeric
 947         //
 948         private static int takeNumber(String s, int i, List<Object> acc) {


1181         @Override
1182         public int hashCode() {
1183             return version.hashCode();
1184         }
1185 
1186         /**
1187          * Returns the string from which this version was parsed.
1188          *
1189          * @return The string from which this version was parsed.
1190          */
1191         @Override
1192         public String toString() {
1193             return version;
1194         }
1195 
1196     }
1197 
1198 
1199     private final String name;
1200     private final Version version;
1201     private final Set<Modifier> modifiers;
1202     private final boolean open;  // true if modifiers contains OPEN
1203     private final boolean automatic;  // true if modifiers contains AUTOMATIC





1204     private final Set<Requires> requires;
1205     private final Set<Exports> exports;
1206     private final Set<Opens> opens;
1207     private final Set<String> uses;
1208     private final Set<Provides> provides;


1209     private final Set<String> packages;
1210     private final String mainClass;
1211     private final String osName;
1212     private final String osArch;
1213     private final String osVersion;
1214 

1215     private ModuleDescriptor(String name,
1216                              Version version,
1217                              Set<Modifier> modifiers,


1218                              Set<Requires> requires,
1219                              Set<Exports> exports,
1220                              Set<Opens> opens,
1221                              Set<String> uses,
1222                              Set<Provides> provides,
1223                              Set<String> packages,
1224                              String mainClass,
1225                              String osName,
1226                              String osArch,
1227                              String osVersion)
1228     {
1229         this.name = name;
1230         this.version = version;
1231         this.modifiers = emptyOrUnmodifiableSet(modifiers);
1232         this.open = modifiers.contains(Modifier.OPEN);
1233         this.automatic = modifiers.contains(Modifier.AUTOMATIC);

1234         assert (requires.stream().map(Requires::name).distinct().count()
1235                 == requires.size());
1236         this.requires = emptyOrUnmodifiableSet(requires);
1237         this.exports = emptyOrUnmodifiableSet(exports);
1238         this.opens = emptyOrUnmodifiableSet(opens);
1239         this.uses = emptyOrUnmodifiableSet(uses);
1240         this.provides = emptyOrUnmodifiableSet(provides);
1241 
1242         this.packages = emptyOrUnmodifiableSet(packages);
1243         this.mainClass = mainClass;
1244         this.osName = osName;
1245         this.osArch = osArch;
1246         this.osVersion = osVersion;
1247     }
1248 
1249     /**


























1250      * Creates a module descriptor from its components.
1251      * The arguments are pre-validated and sets are unmodifiable sets.
1252      */
1253     ModuleDescriptor(String name,
1254                      Version version,
1255                      Set<Modifier> modifiers,


1256                      Set<Requires> requires,
1257                      Set<Exports> exports,
1258                      Set<Opens> opens,
1259                      Set<String> uses,
1260                      Set<Provides> provides,
1261                      Set<String> packages,
1262                      String mainClass,
1263                      String osName,
1264                      String osArch,
1265                      String osVersion,
1266                      int hashCode,
1267                      boolean unused) {
1268         this.name = name;
1269         this.version = version;
1270         this.modifiers = modifiers;
1271         this.open = modifiers.contains(Modifier.OPEN);
1272         this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1273         this.requires = requires;
1274         this.exports = exports;
1275         this.opens = opens;
1276         this.uses = uses;
1277         this.provides = provides;
1278         this.packages = packages;
1279         this.mainClass = mainClass;
1280         this.osName = osName;
1281         this.osArch = osArch;
1282         this.osVersion = osVersion;
1283         this.hash = hashCode;
1284     }
1285 
1286     /**
1287      * <p> Returns the module name. </p>
1288      *
1289      * @return The module name
1290      */
1291     public String name() {
1292         return name;
1293     }
1294 
1295     /**
1296      * <p> Returns the set of module modifiers. </p>
1297      *
1298      * @return A possibly-empty unmodifiable set of modifiers
1299      */
1300     public Set<Modifier> modifiers() {
1301         return modifiers;
1302     }
1303 
1304     /**
1305      * <p> Returns {@code true} if this is an open module. </p>
1306      *
1307      * <p> This method is equivalent to testing if the set of {@link #modifiers
1308      * modifiers} contains the {@link Modifier#OPEN OPEN} modifier. </p>

1309      *
1310      * @return  {@code true} if this is an open module
1311      */
1312     public boolean isOpen() {
1313         return open;
1314     }
1315 
1316     /**
1317      * <p> Returns {@code true} if this is an automatic module. </p>
1318      *
1319      * <p> This method is equivalent to testing if the set of {@link #modifiers
1320      * modifiers} contains the {@link Modifier#OPEN AUTOMATIC} modifier. </p>




1321      *
1322      * @return  {@code true} if this is an automatic module
1323      */
1324     public boolean isAutomatic() {
1325         return automatic;
1326     }
1327 
1328     /**
1329      * <p> Returns the set of module dependences. </p>



1330      *
1331      * <p> The set includes a dependency on "{@code java.base}" when this
1332      * module is not named "{@code java.base}". If this module is an automatic
1333      * module then it does not have a dependency on any module other than
1334      * "{@code java.base}". </p>





1335      *
1336      * @return  A possibly-empty unmodifiable set of {@link Requires} objects
1337      */
1338     public Set<Requires> requires() {
1339         return requires;
1340     }
1341 
1342     /**
1343      * <p> Returns the set of exported packages. </p>
1344      *
1345      * <p> If this module is an automatic module then the set of exports
1346      * is empty. </p>
1347      *
1348      * @return  A possibly-empty unmodifiable set of exported packages
1349      */
1350     public Set<Exports> exports() {
1351         return exports;
1352     }
1353 
1354     /**
1355      * <p> Returns the set of open packages. </p>
1356      *
1357      * <p> If this module is an open module or an automatic module then the
1358      * set of open packages is empty. </p>






1359      *
1360      * @return  A possibly-empty unmodifiable set of open packages
1361      */
1362     public Set<Opens> opens() {
1363         return opens;
1364     }
1365 
1366     /**
1367      * <p> Returns the set of service dependences. </p>
1368      *
1369      * <p> If this module is an automatic module then the set of service
1370      * dependences is empty. </p>
1371      *
1372      * @return  A possibly-empty unmodifiable set of the fully qualified class
1373      *          names of the service types used
1374      */
1375     public Set<String> uses() {
1376         return uses;
1377     }
1378 
1379     /**
1380      * <p> Returns the set of services that the module provides. </p>
1381      *
1382      * @return The possibly-empty unmodifiable set of the services that this
1383      *         module provides
1384      */
1385     public Set<Provides> provides() {
1386         return provides;
1387     }
1388 
1389     /**
1390      * <p> Returns the module version. </p>
1391      *
1392      * @return This module's version
1393      */
1394     public Optional<Version> version() {
1395         return Optional.ofNullable(version);
1396     }
1397 
1398     /**
1399      * <p> Returns a string containing the module name and, if present, its
1400      * version. </p>
1401      *
1402      * @return A string containing the module name and, if present, its
1403      *         version.
1404      */
1405     public String toNameAndVersion() {
1406         if (version != null) {
1407             return name() + "@" + version;
1408         } else {
1409             return name();
1410         }
1411     }
1412 
1413     /**
1414      * <p> Returns the module main class. </p>
1415      *
1416      * @return The fully qualified class name of the module's main class
1417      */
1418     public Optional<String> mainClass() {
1419         return Optional.ofNullable(mainClass);
1420     }
1421 
1422     /**
1423      * Returns the operating system name if the module is operating system
1424      * specific.
1425      *
1426      * @return The operating system name or an empty {@code Optional}
1427      *         if the module is not operating system specific
1428      */
1429     public Optional<String> osName() {
1430         return Optional.ofNullable(osName);
1431     }
1432 
1433     /**
1434      * Returns the operating system architecture if the module is operating
1435      * system architecture specific.
1436      *
1437      * @return The operating system architecture or an empty {@code Optional}
1438      *         if the module is not operating system architecture specific
1439      */
1440     public Optional<String> osArch() {
1441         return Optional.ofNullable(osArch);
1442     }
1443 
1444     /**
1445      * Returns the operating system version if the module is operating
1446      * system version specific.
1447      *
1448      * @return The operating system version or an empty {@code Optional}
1449      *         if the module is not operating system version specific
1450      */
1451     public Optional<String> osVersion() {
1452         return Optional.ofNullable(osVersion);
1453     }
1454 
1455     /**
1456      * Returns the set of packages in the module.
1457      *
1458      * @return A possibly-empty unmodifiable set of the packages in the module
1459      */
1460     public Set<String> packages() {
1461         return packages;
1462     }
1463 
1464 
1465     /**
1466      * A builder for building {@link ModuleDescriptor} objects.
1467      *
1468      * <p> {@code ModuleDescriptor} defines the {@link #newModule newModule},
1469      * {@link #newOpenModule newOpenModule}, and {@link #newAutomaticModule
1470      * newAutomaticModule} methods to create builders for building
1471      * <em>normal</em>, open, and automatic modules. </p>
1472      *
1473      * <p> The set of packages in the module are accumulated by the {@code
1474      * Builder} as the {@link ModuleDescriptor.Builder#exports(String) exports},
1475      * {@link ModuleDescriptor.Builder#opens(String) opens},
1476      * {@link ModuleDescriptor.Builder#packages(Set) packages},
1477      * {@link ModuleDescriptor.Builder#provides(String,List) provides}, and
1478      * {@link ModuleDescriptor.Builder#mainClass(String) mainClass} methods are
1479      * invoked. </p>
1480      *
1481      * <p> The module names, package names, and class names that are parameters
1482      * specified to the builder methods are the module names, package names,
1483      * and qualified names of classes (in named packages) as defined in the
1484      * <cite>The Java&trade; Language Specification</cite>. </p>
1485      *
1486      * <p> Example usage: </p>
1487      * <pre>{@code    ModuleDescriptor descriptor = ModuleDescriptor.newModule("stats.core")
1488      *         .requires("java.base")
1489      *         .exports("org.acme.stats.core.clustering")
1490      *         .exports("org.acme.stats.core.regression")
1491      *         .packages(Set.of("org.acme.stats.core.internal"))
1492      *         .build();
1493      * }</pre>
1494      *
1495      * @apiNote A {@code Builder} checks the components and invariants as
1496      * components are added to the builder. The rationale for this is to detect
1497      * errors as early as possible and not defer all validation to the
1498      * {@link #build build} method.

1499      *
1500      * @since 9
1501      * @spec JPMS
1502      */
1503     public static final class Builder {
1504         final String name;
1505         final boolean strict;
1506         final Set<Modifier> modifiers;
1507         final boolean open;
1508         final boolean automatic;
1509         final Set<String> packages = new HashSet<>();
1510         final Map<String, Requires> requires = new HashMap<>();
1511         final Map<String, Exports> exports = new HashMap<>();
1512         final Map<String, Opens> opens = new HashMap<>();

1513         final Set<String> uses = new HashSet<>();
1514         final Map<String, Provides> provides = new HashMap<>();
1515         Version version;
1516         String osName;
1517         String osArch;
1518         String osVersion;
1519         String mainClass;
1520 
1521         /**
1522          * Initializes a new builder with the given module name.
1523          *
1524          * If {@code strict} is {@code true} then module, package, and class
1525          * names are checked to ensure they are legal names. In addition, the
1526          * {@link #build buid} method will add "{@code requires java.base}" if
1527          * the dependency is not declared.
1528          */
1529         Builder(String name, boolean strict, Set<Modifier> modifiers) {
1530             this.name = (strict) ? requireModuleName(name) : name;
1531             this.strict = strict;
1532             this.modifiers = modifiers;
1533             this.open = modifiers.contains(Modifier.OPEN);
1534             this.automatic = modifiers.contains(Modifier.AUTOMATIC);
1535             assert !open || !automatic;



1536         }
1537 
1538         /**
1539          * Returns a snapshot of the packages in the module.

1540          */
1541         /* package */ Set<String> packages() {
1542             return Collections.unmodifiableSet(packages);








1543         }
1544 
1545         /**
1546          * Adds a dependence on a module.
1547          *
1548          * @param  req
1549          *         The dependence
1550          *
1551          * @return This builder
1552          *
1553          * @throws IllegalArgumentException
1554          *         If the dependence is on the module that this builder was
1555          *         initialized to build
1556          * @throws IllegalStateException
1557          *         If the dependence on the module has already been declared
1558          *         or this builder is for an automatic module
1559          */
1560         public Builder requires(Requires req) {
1561             if (automatic)
1562                 throw new IllegalStateException("Automatic modules cannot declare"
1563                                                 + " dependences");
1564             String mn = req.name();
1565             if (name.equals(mn))
1566                 throw new IllegalArgumentException("Dependence on self");
1567             if (requires.containsKey(mn))
1568                 throw new IllegalStateException("Dependence upon " + mn
1569                                                 + " already declared");
1570             requires.put(mn, req);
1571             return this;
1572         }
1573 
1574         /**
1575          * Adds a dependence on a module with the given (and possibly empty)
1576          * set of modifiers. The dependence includes the version of the
1577          * module that that was recorded at compile-time.
1578          *
1579          * @param  ms
1580          *         The set of modifiers
1581          * @param  mn
1582          *         The module name
1583          * @param  compiledVersion
1584          *         The version of the module recorded at compile-time
1585          *
1586          * @return This builder
1587          *
1588          * @throws IllegalArgumentException
1589          *         If the module name is {@code null}, is not a legal module
1590          *         name, or is equal to the module name that this builder
1591          *         was initialized to build
1592          * @throws IllegalStateException
1593          *         If the dependence on the module has already been declared
1594          *         or this builder is for an automatic module
1595          */
1596         public Builder requires(Set<Requires.Modifier> ms,
1597                                 String mn,
1598                                 Version compiledVersion) {
1599             Objects.requireNonNull(compiledVersion);
1600             if (strict)
1601                 mn = requireModuleName(mn);
1602             return requires(new Requires(ms, mn, compiledVersion));
1603         }
1604 
1605         /* package */Builder requires(Set<Requires.Modifier> ms,
1606                                       String mn,
1607                                       String compiledVersion) {
1608             Version v = null;
1609             try {
1610                 v = Version.parse(compiledVersion);
1611             } catch (IllegalArgumentException e) {
1612                 // for now, drop un-parsable version when non-strict
1613                 if (strict) throw e;
1614             }
1615             if (v == null) {
1616                 return requires(ms, mn);
1617             } else {
1618                 return requires(ms, mn, v);
1619             }
1620         }
1621 
1622         /**
1623          * Adds a dependence on a module with the given (and possibly empty)
1624          * set of modifiers.
1625          *
1626          * @param  ms
1627          *         The set of modifiers
1628          * @param  mn
1629          *         The module name
1630          *
1631          * @return This builder
1632          *
1633          * @throws IllegalArgumentException
1634          *         If the module name is {@code null}, is not a legal module
1635          *         name, or is equal to the module name that this builder
1636          *         was initialized to build
1637          * @throws IllegalStateException
1638          *         If the dependence on the module has already been declared
1639          *         or this builder is for an automatic module
1640          */
1641         public Builder requires(Set<Requires.Modifier> ms, String mn) {
1642             if (strict)
1643                 mn = requireModuleName(mn);
1644             return requires(new Requires(ms, mn, null));
1645         }
1646 
1647         /**
1648          * Adds a dependence on a module with an empty set of modifiers.
1649          *
1650          * @param  mn
1651          *         The module name
1652          *
1653          * @return This builder
1654          *
1655          * @throws IllegalArgumentException
1656          *         If the module name is {@code null}, is not a legal module
1657          *         name, or is equal to the module name that this builder
1658          *         was initialized to build
1659          * @throws IllegalStateException
1660          *         If the dependence on the module has already been declared
1661          *         or this builder is for an automatic module
1662          */
1663         public Builder requires(String mn) {
1664             return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
1665         }
1666 
1667         /**
1668          * Adds an exported package.
1669          *
1670          * @param  e
1671          *         The export
1672          *
1673          * @return This builder
1674          *
1675          * @throws IllegalStateException
1676          *         If the {@link Exports#source package} is already declared as
1677          *         exported or this builder is for an automatic module

1678          */
1679         public Builder exports(Exports e) {
1680             if (automatic) {
1681                 throw new IllegalStateException("Automatic modules cannot declare"
1682                                                  + " exported packages");


1683             }
1684             String source = e.source();
1685             if (exports.containsKey(source)) {
1686                 throw new IllegalStateException("Exported package " + source
1687                                                  + " already declared");
1688             }

1689             exports.put(source, e);
1690             packages.add(source);
1691             return this;
1692         }
1693 
1694         /**
1695          * Adds an exported package with the given (and possibly empty) set of
1696          * modifiers. The package is exported to a set of target modules.
1697          *
1698          * @param  ms
1699          *         The set of modifiers
1700          * @param  pn
1701          *         The package name
1702          * @param  targets
1703          *         The set of target modules names
1704          *
1705          * @return This builder
1706          *
1707          * @throws IllegalArgumentException
1708          *         If the package name is {@code null} or is not a legal
1709          *         package name, the set of target modules is empty, or the set
1710          *         of target modules contains a name that is not a legal module
1711          *         name
1712          * @throws IllegalStateException
1713          *         If the package is already declared as exported
1714          *         or this builder is for an automatic module

1715          */
1716         public Builder exports(Set<Exports.Modifier> ms,
1717                                String pn,
1718                                Set<String> targets)
1719         {
1720             Exports e = new Exports(ms, pn, targets);
1721 
1722             // check targets
1723             targets = e.targets();
1724             if (targets.isEmpty())
1725                 throw new IllegalArgumentException("Empty target set");
1726             if (strict) {
1727                 requirePackageName(e.source());
1728                 targets.stream().forEach(Checks::requireModuleName);
1729             }
1730             return exports(e);
1731         }
1732 
1733         /**
1734          * Adds an exported package with the given (and possibly empty) set of
1735          * modifiers. The package is exported to all modules.
1736          *
1737          * @param  ms
1738          *         The set of modifiers
1739          * @param  pn
1740          *         The package name
1741          *
1742          * @return This builder
1743          *
1744          * @throws IllegalArgumentException
1745          *         If the package name is {@code null} or is not a legal
1746          *         package name
1747          * @throws IllegalStateException
1748          *         If the package is already declared as exported
1749          *         or this builder is for an automatic module

1750          */
1751         public Builder exports(Set<Exports.Modifier> ms, String pn) {
1752             if (strict) {
1753                 requirePackageName(pn);
1754             }
1755             Exports e = new Exports(ms, pn, Collections.emptySet());
1756             return exports(e);
1757         }
1758 
1759         /**
1760          * Adds an exported package. The package is exported to a set of target
1761          * modules.
1762          *
1763          * @param  pn
1764          *         The package name
1765          * @param  targets
1766          *         The set of target modules names
1767          *
1768          * @return This builder
1769          *
1770          * @throws IllegalArgumentException
1771          *         If the package name is {@code null} or is not a legal
1772          *         package name, the set of target modules is empty, or the set
1773          *         of target modules contains a name that is not a legal module
1774          *         name
1775          * @throws IllegalStateException
1776          *         If the package is already declared as exported
1777          *         or this builder is for an automatic module

1778          */
1779         public Builder exports(String pn, Set<String> targets) {
1780             return exports(Collections.emptySet(), pn, targets);
1781         }
1782 
1783         /**
1784          * Adds an exported package. The package is exported to all modules.
1785          *
1786          * @param  pn
1787          *         The package name
1788          *
1789          * @return This builder
1790          *
1791          * @throws IllegalArgumentException
1792          *         If the package name is {@code null} or is not a legal
1793          *         package name
1794          * @throws IllegalStateException
1795          *         If the package is already declared as exported
1796          *         or this builder is for an automatic module

1797          */
1798         public Builder exports(String pn) {
1799             return exports(Collections.emptySet(), pn);
1800         }
1801 
1802         /**
1803          * Adds an open package.
1804          *
1805          * @param  obj
1806          *         The {@code Opens} object
1807          *
1808          * @return This builder
1809          *
1810          * @throws IllegalStateException
1811          *         If the package is already declared as open, or this is a
1812          *         builder for an open module or automatic module

1813          */
1814         public Builder opens(Opens obj) {
1815             if (open || automatic) {
1816                 throw new IllegalStateException("Open or automatic modules cannot"
1817                                                 + " declare open packages");
1818             }


1819             String source = obj.source();




1820             if (opens.containsKey(source)) {
1821                 throw new IllegalStateException("Open package " + source
1822                                                 + " already declared");
1823             }

1824             opens.put(source, obj);
1825             packages.add(source);
1826             return this;
1827         }
1828 
1829 
1830         /**
1831          * Adds an open package with the given (and possibly empty) set of
1832          * modifiers. The package is open to a set of target modules.
1833          *
1834          * @param  ms
1835          *         The set of modifiers
1836          * @param  pn
1837          *         The package name
1838          * @param  targets
1839          *         The set of target modules names
1840          *
1841          * @return This builder
1842          *
1843          * @throws IllegalArgumentException
1844          *         If the package name is {@code null} or is not a legal
1845          *         package name, the set of target modules is empty, or the set
1846          *         of target modules contains a name that is not a legal module
1847          *         name
1848          * @throws IllegalStateException
1849          *         If the package is already declared as open, or this is a
1850          *         builder for an open module or automatic module

1851          */
1852         public Builder opens(Set<Opens.Modifier> ms,
1853                              String pn,
1854                              Set<String> targets)
1855         {
1856             Opens opens = new Opens(ms, pn, targets);
1857 
1858             // check targets
1859             targets = opens.targets();
1860             if (targets.isEmpty())
1861                 throw new IllegalArgumentException("Empty target set");
1862             if (strict) {
1863                 requirePackageName(opens.source());
1864                 targets.stream().forEach(Checks::requireModuleName);
1865             }
1866             return opens(opens);
1867         }
1868 
1869         /**
1870          * Adds an open package with the given (and possibly empty) set of
1871          * modifiers. The package is open to all modules.
1872          *
1873          * @param  ms
1874          *         The set of modifiers
1875          * @param  pn
1876          *         The package name
1877          *
1878          * @return This builder
1879          *
1880          * @throws IllegalArgumentException
1881          *         If the package name is {@code null} or is not a legal
1882          *         package name
1883          * @throws IllegalStateException
1884          *         If the package is already declared as open, or this is a
1885          *         builder for an open module or automatic module

1886          */
1887         public Builder opens(Set<Opens.Modifier> ms, String pn) {
1888             if (strict) {
1889                 requirePackageName(pn);
1890             }
1891             Opens e = new Opens(ms, pn, Collections.emptySet());
1892             return opens(e);
1893         }
1894 
1895         /**
1896          * Adds an open package. The package is open to a set of target modules.

1897          *
1898          * @param  pn
1899          *         The package name
1900          * @param  targets
1901          *         The set of target modules names
1902          *
1903          * @return This builder
1904          *
1905          * @throws IllegalArgumentException
1906          *         If the package name is {@code null} or is not a legal
1907          *         package name, the set of target modules is empty, or the set
1908          *         of target modules contains a name that is not a legal module
1909          *         name
1910          * @throws IllegalStateException
1911          *         If the package is already declared as open, or this is a
1912          *         builder for an open module or automatic module

1913          */
1914         public Builder opens(String pn, Set<String> targets) {
1915             return opens(Collections.emptySet(), pn, targets);
1916         }
1917 
1918         /**
1919          * Adds an open package. The package is open to all modules.
1920          *
1921          * @param  pn
1922          *         The package name
1923          *
1924          * @return This builder
1925          *
1926          * @throws IllegalArgumentException
1927          *         If the package name is {@code null} or is not a legal
1928          *         package name
1929          * @throws IllegalStateException
1930          *         If the package is already declared as open, or this is a
1931          *         builder for an open module or automatic module

1932          */
1933         public Builder opens(String pn) {
1934             return opens(Collections.emptySet(), pn);
1935         }
1936 
1937         /**
1938          * Adds a service dependence.
1939          *
1940          * @param  service
1941          *         The service type
1942          *
1943          * @return This builder
1944          *
1945          * @throws IllegalArgumentException
1946          *         If the service type is {@code null} or not a qualified name of
1947          *         a class in a named package
1948          * @throws IllegalStateException
1949          *         If a dependency on the service type has already been declared
1950          *         or this is a builder for an an automatic module
1951          */
1952         public Builder uses(String service) {
1953             if (automatic)
1954                 throw new IllegalStateException("Automatic modules can not declare"
1955                                                 + " service dependences");
1956             if (uses.contains(requireServiceTypeName(service)))
1957                 throw new IllegalStateException("Dependence upon service "
1958                                                 + service + " already declared");
1959             uses.add(service);
1960             return this;
1961         }
1962 
1963         /**
1964          * Provides a service with one or more implementations. The package for
1965          * each {@link Provides#providers provider} (or provider factory) is
1966          * added to the module if not already added.
1967          *
1968          * @param  p
1969          *         The provides
1970          *
1971          * @return This builder
1972          *
1973          * @throws IllegalStateException
1974          *         If the providers for the service type have already been
1975          *         declared
1976          */
1977         public Builder provides(Provides p) {
1978             String service = p.service();
1979             if (provides.containsKey(service))
1980                 throw new IllegalStateException("Providers of service "
1981                                                 + service + " already declared");
1982             provides.put(service, p);
1983             p.providers().forEach(name -> packages.add(packageName(name)));
1984             return this;
1985         }
1986 
1987         /**
1988          * Provides implementations of a service. The package for each provider
1989          * (or provider factory) is added to the module if not already added.
1990          *
1991          * @param  service
1992          *         The service type
1993          * @param  providers
1994          *         The list of provider or provider factory class names
1995          *
1996          * @return This builder
1997          *
1998          * @throws IllegalArgumentException
1999          *         If the service type or any of the provider class names is
2000          *         {@code null} or not a qualified name of a class in a named
2001          *         package, or the list of provider class names is empty
2002          * @throws IllegalStateException
2003          *         If the providers for the service type have already been
2004          *         declared
2005          */
2006         public Builder provides(String service, List<String> providers) {
2007             Provides p = new Provides(service, providers);




2008 
2009             // check providers after the set has been copied.
2010             List<String> providerNames = p.providers();
2011             if (providerNames.isEmpty())
2012                 throw new IllegalArgumentException("Empty providers set");
2013             if (strict) {
2014                 requireServiceTypeName(p.service());
2015                 providerNames.forEach(Checks::requireServiceProviderName);
2016             } else {
2017                 // Disallow service/providers in unnamed package
2018                 String pn = packageName(service);
2019                 if (pn.isEmpty()) {
2020                     throw new IllegalArgumentException(service
2021                                                        + ": unnamed package");
2022                 }
2023                 for (String name : providerNames) {
2024                     pn = packageName(name);
2025                     if (pn.isEmpty()) {
2026                         throw new IllegalArgumentException(name
2027                                                            + ": unnamed package");
2028                     }
2029                 }
2030             }
2031             return provides(p);













2032         }
2033 
2034         /**
2035          * Adds packages to the module. All packages in the set of package names
2036          * that are not in the module are added to module.
2037          *
2038          * @param  pns
2039          *         The (possibly empty) set of package names
2040          *
2041          * @return This builder
2042          *
2043          * @throws IllegalArgumentException
2044          *         If any of the package names is {@code null} or is not a
2045          *         legal package name




2046          */
2047         public Builder packages(Set<String> pns) {
2048             if (strict) {
2049                 pns = new HashSet<>(pns);
2050                 pns.forEach(Checks::requirePackageName);






























2051             }
2052             this.packages.addAll(pns);
2053             return this;
2054         }
2055 
2056         /**
2057          * Sets the module version.
2058          *
2059          * @param  v
2060          *         The version
2061          *
2062          * @return This builder
2063          */
2064         public Builder version(Version v) {
2065             version = requireNonNull(v);
2066             return this;
2067         }
2068 
2069         /**
2070          * Sets the module version.
2071          *
2072          * @param  vs
2073          *         The version string to parse
2074          *
2075          * @return This builder
2076          *
2077          * @throws IllegalArgumentException
2078          *         If {@code vs} is {@code null} or cannot be parsed as a
2079          *         version string
2080          *
2081          * @see Version#parse(String)
2082          */
2083         public Builder version(String vs) {
2084             Version v;
2085             if (strict) {
2086                 v = Version.parse(vs);
2087             } else {
2088                 try {
2089                     v = Version.parse(vs);
2090                 } catch (IllegalArgumentException ignore) {
2091                     // for now, ignore when non-strict
2092                     return this;
2093                 }
2094             }
2095             return version(v);
2096         }
2097 
2098         /**
2099          * Sets the module main class. The package for the main class is added
2100          * to the module if not already added.
2101          *
2102          * @param  mc
2103          *         The module main class
2104          *
2105          * @return This builder
2106          *
2107          * @throws IllegalArgumentException
2108          *         If {@code mainClass} is {@code null} or not a qualified
2109          *         name of a class in a named package
2110          */
2111         public Builder mainClass(String mc) {
2112             String pn;
2113             if (strict) {
2114                 mc = requireQualifiedClassName("main class name", mc);
2115                 pn = packageName(mc);
2116                 assert !pn.isEmpty();
2117             } else {
2118                 // Disallow main class in unnamed package
2119                 pn = packageName(mc);
2120                 if (pn.isEmpty()) {
2121                     throw new IllegalArgumentException(mc + ": unnamed package");
2122                 }
2123             }
2124             mainClass = mc;
2125             packages.add(pn);
2126             return this;
2127         }
2128 
2129         /**
2130          * Sets the operating system name.
2131          *
2132          * @param  name
2133          *         The operating system name
2134          *
2135          * @return This builder
2136          *
2137          * @throws IllegalArgumentException
2138          *         If {@code name} is {@code null} or the empty String
2139          */
2140         public Builder osName(String name) {
2141             if (name == null || name.isEmpty())
2142                 throw new IllegalArgumentException("OS name is null or empty");
2143             osName = name;
2144             return this;
2145         }
2146 
2147         /**
2148          * Sets the operating system architecture.
2149          *
2150          * @param  arch
2151          *         The operating system architecture
2152          *
2153          * @return This builder
2154          *
2155          * @throws IllegalArgumentException
2156          *         If {@code name} is {@code null} or the empty String
2157          */
2158         public Builder osArch(String arch) {
2159             if (arch == null || arch.isEmpty())
2160                 throw new IllegalArgumentException("OS arch is null or empty");
2161             osArch = arch;
2162             return this;
2163         }
2164 
2165         /**
2166          * Sets the operating system version.
2167          *
2168          * @param  version
2169          *         The operating system version
2170          *
2171          * @return This builder
2172          *
2173          * @throws IllegalArgumentException
2174          *         If {@code name} is {@code null} or the empty String
2175          */
2176         public Builder osVersion(String version) {
2177             if (version == null || version.isEmpty())
2178                 throw new IllegalArgumentException("OS version is null or empty");
2179             osVersion = version;
2180             return this;
2181         }
2182 
2183         /**
2184          * Builds and returns a {@code ModuleDescriptor} from its components.
2185          *
2186          * <p> The module will require "{@code java.base}" even if the dependence
2187          * has not been declared (the exception is when building a module named
2188          * "{@code java.base}" as it cannot require itself). The dependence on
2189          * "{@code java.base}" will have the {@link
2190          * java.lang.module.ModuleDescriptor.Requires.Modifier#MANDATED MANDATED}
2191          * modifier if the dependence was not declared. </p>
2192          *
2193          * @return The module descriptor
2194          */
2195         public ModuleDescriptor build() {
2196             Set<Requires> requires = new HashSet<>(this.requires.values());






2197             Set<Exports> exports = new HashSet<>(this.exports.values());
2198             Set<Opens> opens = new HashSet<>(this.opens.values());
2199 
2200             // add dependency on java.base
2201             if (strict
2202                     && !name.equals("java.base")
2203                     && !this.requires.containsKey("java.base")) {
2204                 requires.add(new Requires(Set.of(Requires.Modifier.MANDATED),
2205                                           "java.base",
2206                                           null));
2207             }
2208 
2209             Set<Provides> provides = new HashSet<>(this.provides.values());
2210 
2211             return new ModuleDescriptor(name,
2212                                         version,
2213                                         modifiers,


2214                                         requires,
2215                                         exports,
2216                                         opens,
2217                                         uses,
2218                                         provides,
2219                                         packages,
2220                                         mainClass,
2221                                         osName,
2222                                         osArch,
2223                                         osVersion);
2224         }
2225 
2226     }
2227 
2228     /**
2229      * Compares this module descriptor to another.
2230      *
2231      * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
2232      * module names lexicographically. Where the module names are equal then the
2233      * module versions are compared. When comparing the module versions then a
2234      * module descriptor with a version is considered to succeed a module
2235      * descriptor that does not have a version. Where the module names are equal
2236      * and the versions are equal (or not present in both), then the set of
2237      * modifiers are compared. Sets of modifiers are compared by comparing
2238      * a <em>binary value</em> computed for each set. If a modifier is present
2239      * in the set then the bit at the position of its ordinal is {@code 1}
2240      * in the binary value, otherwise {@code 0}. If the two set of modifiers
2241      * are also equal then the other components of the module descriptors are
2242      * compared in a manner that is consistent with {@code equals}. </p>
2243      *
2244      * @param  that
2245      *         The module descriptor to compare
2246      *
2247      * @return A negative integer, zero, or a positive integer if this module
2248      *         descriptor is less than, equal to, or greater than the given
2249      *         module descriptor
2250      */
2251     @Override
2252     public int compareTo(ModuleDescriptor that) {
2253         if (this == that) return 0;
2254 
2255         int c = this.name().compareTo(that.name());
2256         if (c != 0) return c;
2257 
2258         c = compare(this.version, that.version);
2259         if (c != 0) return c;
2260 
2261         long v1 = modsValue(this.modifiers());
2262         long v2 = modsValue(that.modifiers());
2263         c = Long.compare(v1, v2);
2264         if (c != 0) return c;
2265 
2266         c = compare(this.requires, that.requires);
2267         if (c != 0) return c;
2268 
2269         c = compare(this.packages, that.packages);
2270         if (c != 0) return c;
2271 
2272         c = compare(this.exports, that.exports);
2273         if (c != 0) return c;
2274 
2275         c = compare(this.opens, that.opens);
2276         if (c != 0) return c;
2277 
2278         c = compare(this.uses, that.uses);
2279         if (c != 0) return c;
2280 
2281         c = compare(this.provides, that.provides);
2282         if (c != 0) return c;
2283 
2284         c = compare(this.mainClass, that.mainClass);
2285         if (c != 0) return c;
2286 
2287         c = compare(this.osName, that.osName);
2288         if (c != 0) return c;
2289 
2290         c = compare(this.osArch, that.osArch);
2291         if (c != 0) return c;
2292 
2293         c = compare(this.osVersion, that.osVersion);
2294         if (c != 0) return c;
2295 
2296         return 0;





2297     }
2298 
2299     /**
2300      * Tests this module descriptor for equality with the given object.
2301      *
2302      * <p> If the given object is not a {@code ModuleDescriptor} then this
2303      * method returns {@code false}. Two module descriptors are equal if each
2304      * of their corresponding components is equal. </p>
2305      *
2306      * <p> This method satisfies the general contract of the {@link
2307      * java.lang.Object#equals(Object) Object.equals} method. </p>
2308      *
2309      * @param   ob
2310      *          the object to which this object is to be compared
2311      *
2312      * @return  {@code true} if, and only if, the given object is a module
2313      *          descriptor that is equal to this module descriptor
2314      */
2315     @Override
2316     public boolean equals(Object ob) {
2317         if (ob == this)
2318             return true;
2319         if (!(ob instanceof ModuleDescriptor))
2320             return false;
2321         ModuleDescriptor that = (ModuleDescriptor)ob;
2322         return (name.equals(that.name)
2323                 && modifiers.equals(that.modifiers)


2324                 && requires.equals(that.requires)
2325                 && Objects.equals(packages, that.packages)
2326                 && exports.equals(that.exports)
2327                 && opens.equals(that.opens)
2328                 && uses.equals(that.uses)
2329                 && provides.equals(that.provides)
2330                 && Objects.equals(version, that.version)
2331                 && Objects.equals(mainClass, that.mainClass)
2332                 && Objects.equals(osName, that.osName)
2333                 && Objects.equals(osArch, that.osArch)
2334                 && Objects.equals(osVersion, that.osVersion));

2335     }
2336 


2337     /**
2338      * Computes a hash code for this module descriptor.
2339      *
2340      * <p> The hash code is based upon the components of the module descriptor,
2341      * and satisfies the general contract of the {@link Object#hashCode
2342      * Object.hashCode} method. </p>
2343      *
2344      * @return The hash-code value for this module descriptor
2345      */
2346     @Override
2347     public int hashCode() {
2348         int hc = hash;
2349         if (hc == 0) {
2350             hc = name.hashCode();
2351             hc = hc * 43 + Objects.hashCode(modifiers);


2352             hc = hc * 43 + requires.hashCode();
2353             hc = hc * 43 + Objects.hashCode(packages);
2354             hc = hc * 43 + exports.hashCode();
2355             hc = hc * 43 + opens.hashCode();
2356             hc = hc * 43 + uses.hashCode();
2357             hc = hc * 43 + provides.hashCode();
2358             hc = hc * 43 + Objects.hashCode(version);
2359             hc = hc * 43 + Objects.hashCode(mainClass);
2360             hc = hc * 43 + Objects.hashCode(osName);
2361             hc = hc * 43 + Objects.hashCode(osArch);
2362             hc = hc * 43 + Objects.hashCode(osVersion);

2363             if (hc == 0)
2364                 hc = -1;
2365             hash = hc;
2366         }
2367         return hc;
2368     }
2369     private transient int hash;  // cached hash code
2370 
2371     /**
2372      * <p> Returns a string describing the module. </p>
2373      *
2374      * @return A string describing the module
2375      */
2376     @Override
2377     public String toString() {
2378         StringBuilder sb = new StringBuilder();
2379 
2380         if (isOpen())
2381             sb.append("open ");
2382         sb.append("module { name: ").append(toNameAndVersion());
2383         if (!requires.isEmpty())
2384             sb.append(", ").append(requires);
2385         if (!uses.isEmpty())
2386             sb.append(", uses: ").append(uses);
2387         if (!exports.isEmpty())
2388             sb.append(", exports: ").append(exports);
2389         if (!opens.isEmpty())
2390             sb.append(", opens: ").append(opens);
2391         if (!provides.isEmpty()) {
2392             sb.append(", provides: ").append(provides);
2393         }
2394         sb.append(" }");
2395         return sb.toString();
2396     }
2397 
2398 
2399     /**
2400      * Instantiates a builder to build a module descriptor.
2401      *
2402      * @param  name
2403      *         The module name
2404      * @param  ms
2405      *         The set of module modifiers
2406      *
2407      * @return A new builder
2408      *
2409      * @throws IllegalArgumentException
2410      *         If the module name is {@code null} or is not a legal module
2411      *         name, or the set of modifiers contains both {@link Modifier#OPEN
2412      *         OPEN} and {@link Modifier#AUTOMATIC AUTOMATIC}
2413      */
2414     public static Builder newModule(String name, Set<Modifier> ms) {
2415         Set<Modifier> mods = new HashSet<>(ms);
2416         if (mods.contains(Modifier.OPEN) && mods.contains(Modifier.AUTOMATIC))
2417             throw new IllegalArgumentException("OPEN and AUTOMATIC not allowed");
2418         return new Builder(name, true, mods);
2419     }
2420 
2421     /**
2422      * Instantiates a builder to build a module descriptor.
2423      *
2424      * @param  name
2425      *         The module name
2426      *
2427      * @return A new builder
2428      *
2429      * @throws IllegalArgumentException
2430      *         If the module name is {@code null} or is not a legal module
2431      *         name
2432      */
2433     public static Builder newModule(String name) {
2434         return new Builder(name, true, Set.of());
2435     }
2436 
2437     /**
2438      * Instantiates a builder to build a module descriptor for an open module.


2439      *
2440      * <p> The builder for an open module cannot be used to declare any open
2441      * packages. </p>







2442      *
2443      * @param  name
2444      *         The module name
2445      *
2446      * @return A new builder that builds an open module
2447      *
2448      * @throws IllegalArgumentException
2449      *         If the module name is {@code null} or is not a legal module
2450      *         name
2451      */
2452     public static Builder newOpenModule(String name) {
2453         return new Builder(name, true, Set.of(Modifier.OPEN));
2454     }
2455 
2456     /**
2457      * Instantiates a builder to build a module descriptor for an automatic
2458      * module.
2459      *
2460      * <p> The builder for an automatic module cannot be used to declare module
2461      * or service dependences. It also cannot be used to declare any exported
2462      * or open packages. </p>
2463      *
2464      * @param  name
2465      *         The module name
2466      *
2467      * @return A new builder that builds an automatic module
2468      *
2469      * @throws IllegalArgumentException
2470      *         If the module name is {@code null} or is not a legal module
2471      *         name
2472      *
2473      * @see ModuleFinder#of(Path[])
2474      */
2475     public static Builder newAutomaticModule(String name) {
2476         return new Builder(name, true, Set.of(Modifier.AUTOMATIC));
2477     }
2478 
2479 
2480     /**
2481      * Reads the binary form of a module declaration from an input stream
2482      * as a module descriptor.
2483      *
2484      * <p> If the descriptor encoded in the input stream does not indicate a
2485      * set of packages in the module then the {@code packageFinder} will be
2486      * invoked. The set of packages that the {@code packageFinder} returns
2487      * must include all the packages that the module exports, opens, as well
2488      * as the packages of the service implementations that the module provides,
2489      * and the package of the main class (if the module has a main class). If
2490      * the {@code packageFinder} throws an {@link UncheckedIOException} then
2491      * {@link IOException} cause will be re-thrown. </p>
2492      *
2493      * <p> If there are bytes following the module descriptor then it is
2494      * implementation specific as to whether those bytes are read, ignored,
2495      * or reported as an {@code InvalidModuleDescriptorException}. If this
2496      * method fails with an {@code InvalidModuleDescriptorException} or {@code
2497      * IOException} then it may do so after some, but not all, bytes have
2498      * been read from the input stream. It is strongly recommended that the
2499      * stream be promptly closed and discarded if an exception occurs. </p>
2500      *
2501      * @apiNote The {@code packageFinder} parameter is for use when reading
2502      * module descriptors from legacy module-artifact formats that do not
2503      * record the set of packages in the descriptor itself.
2504      *
2505      * @param  in
2506      *         The input stream
2507      * @param  packageFinder
2508      *         A supplier that can produce the set of packages
2509      *
2510      * @return The module descriptor
2511      *
2512      * @throws InvalidModuleDescriptorException
2513      *         If an invalid module descriptor is detected or the set of
2514      *         packages returned by the {@code packageFinder} does not include
2515      *         all of the packages obtained from the module descriptor
2516      * @throws IOException
2517      *         If an I/O error occurs reading from the input stream or {@code
2518      *         UncheckedIOException} is thrown by the package finder
2519      */
2520     public static ModuleDescriptor read(InputStream in,
2521                                         Supplier<Set<String>> packageFinder)
2522         throws IOException
2523     {
2524         return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
2525     }
2526 
2527     /**
2528      * Reads the binary form of a module declaration from an input stream as a
2529      * module descriptor. This method works exactly as specified by the 2-arg
2530      * {@link #read(InputStream,Supplier) read} method with the exception that
2531      * a packager finder is not used to find additional packages when the
2532      * module descriptor read from the stream does not indicate the set of
2533      * packages.
2534      *
2535      * @param  in
2536      *         The input stream
2537      *
2538      * @return The module descriptor
2539      *
2540      * @throws InvalidModuleDescriptorException
2541      *         If an invalid module descriptor is detected
2542      * @throws IOException
2543      *         If an I/O error occurs reading from the input stream
2544      */
2545     public static ModuleDescriptor read(InputStream in) throws IOException {
2546         return ModuleInfo.read(in, null).descriptor();
2547     }
2548 
2549     /**
2550      * Reads the binary form of a module declaration from a byte buffer
2551      * as a module descriptor.
2552      *
2553      * <p> If the descriptor encoded in the byte buffer does not indicate a
2554      * set of packages in the module then the {@code packageFinder} will be
2555      * invoked. The set of packages that the {@code packageFinder} returns
2556      * must include all the packages that the module exports, opens, as well
2557      * as the packages of the service implementations that the module provides,
2558      * and the package of the main class (if the module has a main class). If
2559      * the {@code packageFinder} throws an {@link UncheckedIOException} then
2560      * {@link IOException} cause will be re-thrown. </p>
2561      *
2562      * <p> The module descriptor is read from the buffer stating at index
2563      * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
2564      * position} when this method is invoked. Upon return the buffer's position
2565      * will be equal to {@code p + n} where {@code n} is the number of bytes
2566      * read from the buffer. </p>
2567      *
2568      * <p> If there are bytes following the module descriptor then it is
2569      * implementation specific as to whether those bytes are read, ignored,
2570      * or reported as an {@code InvalidModuleDescriptorException}. If this
2571      * method fails with an {@code InvalidModuleDescriptorException} then it
2572      * may do so after some, but not all, bytes have been read. </p>
2573      *
2574      * @apiNote The {@code packageFinder} parameter is for use when reading
2575      * module descriptors from legacy module-artifact formats that do not
2576      * record the set of packages in the descriptor itself.
2577      *
2578      * @param  bb
2579      *         The byte buffer
2580      * @param  packageFinder
2581      *         A supplier that can produce the set of packages
2582      *
2583      * @return The module descriptor
2584      *
2585      * @throws InvalidModuleDescriptorException
2586      *         If an invalid module descriptor is detected or the set of
2587      *         packages returned by the {@code packageFinder} does not include
2588      *         all of the packages obtained from the module descriptor
2589      */
2590     public static ModuleDescriptor read(ByteBuffer bb,
2591                                         Supplier<Set<String>> packageFinder)
2592     {
2593         return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
2594     }
2595 
2596     /**
2597      * Reads the binary form of a module declaration from a byte buffer as a
2598      * module descriptor. This method works exactly as specified by the 2-arg
2599      * {@link #read(ByteBuffer,Supplier) read} method with the exception that a
2600      * packager finder is not used to find additional packages when the module
2601      * descriptor encoded in the buffer does not indicate the set of packages.
2602      *
2603      * @param  bb
2604      *         The byte buffer
2605      *
2606      * @return The module descriptor
2607      *
2608      * @throws InvalidModuleDescriptorException
2609      *         If an invalid module descriptor is detected
2610      */
2611     public static ModuleDescriptor read(ByteBuffer bb) {
2612         return ModuleInfo.read(bb, null).descriptor();
2613     }
2614 
2615     private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
2616         if (map.isEmpty()) {
2617             return Collections.emptyMap();
2618         } else if (map.size() == 1) {
2619             Map.Entry<K, V> entry = map.entrySet().iterator().next();
2620             return Collections.singletonMap(entry.getKey(), entry.getValue());
2621         } else {
2622             return Collections.unmodifiableMap(map);
2623         }
2624     }
2625 
2626     private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) {
2627         if (set.isEmpty()) {
2628             return Collections.emptySet();
2629         } else if (set.size() == 1) {
2630             return Collections.singleton(set.iterator().next());
2631         } else {
2632             return Collections.unmodifiableSet(set);
2633         }
2634     }
2635 
2636     private static String packageName(String cn) {
2637         int index = cn.lastIndexOf('.');
2638         return (index == -1) ? "" : cn.substring(0, index);
2639     }
2640 
2641     /**
2642      * Returns a string containing the given set of modifiers and label.
2643      */
2644     private static <M> String toString(Set<M> mods, String what) {
2645         return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
2646                               Stream.of(what)))
2647                 .collect(Collectors.joining(" "));
2648     }
2649 
2650     private static <T extends Object & Comparable<? super T>>
2651     int compare(T obj1, T obj2) {
2652         if (obj1 != null) {
2653             return (obj2 != null) ? obj1.compareTo(obj2) : 1;
2654         } else {
2655             return (obj2 == null) ? 0 : -1;
2656         }
2657     }
2658 
2659     /**
2660      * Compares two sets of {@code Comparable} objects.
2661      */
2662     private static <T extends Object & Comparable<? super T>>
2663     int compare(Set<T> s1, Set<T> s2) {
2664         Iterator<T> iterator1 = new TreeSet<>(s1).iterator();
2665         Iterator<T> iterator2 =  new TreeSet<>(s2).iterator();
2666         while (iterator1.hasNext()) {
2667             if (!iterator2.hasNext())
2668                 return 1; // s1 has more elements
2669             T e1 = iterator1.next();
2670             T e2 = iterator2.next();
2671             int c = e1.compareTo(e2);
2672             if (c != 0)
2673                 return c;
2674         }
2675         if (iterator2.hasNext()) {
2676             return -1;  // s2 has more elements
2677         } else {
2678             return 0;
2679         }
2680     }
2681 
2682     private static <E extends Enum<E>> long modsValue(Set<E> set) {
2683         long value = 0;
2684         for (Enum<E> e : set) {
2685             value += 1 << e.ordinal();
2686         }
2687         return value;
2688     }
2689 
2690     static {
2691         /**
2692          * Setup the shared secret to allow code in other packages access
2693          * private package methods in java.lang.module.
2694          */
2695         jdk.internal.misc.SharedSecrets
2696             .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
2697                 @Override
2698                 public Builder newModuleBuilder(String mn,
2699                                                 boolean strict,
2700                                                 Set<ModuleDescriptor.Modifier> modifiers) {
2701                     return new Builder(mn, strict, modifiers);

2702                 }
2703 
2704                 @Override
2705                 public Set<String> packages(ModuleDescriptor.Builder builder) {
2706                     return builder.packages();
2707                 }
2708 
2709                 @Override
2710                 public void requires(ModuleDescriptor.Builder builder,
2711                                      Set<Requires.Modifier> ms,
2712                                      String mn,
2713                                      String compiledVersion) {
2714                     builder.requires(ms, mn, compiledVersion);
2715                 }
2716 
2717                 @Override
2718                 public Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v) {
2719                     return new Requires(ms, mn, v, true);
2720                 }
2721 
2722                 @Override
2723                 public Exports newExports(Set<Exports.Modifier> ms, String source) {
2724                     return new Exports(ms, source, Collections.emptySet(), true);
2725                 }
2726 
2727                 @Override
2728                 public Exports newExports(Set<Exports.Modifier> ms,
2729                                           String source,
2730                                           Set<String> targets) {
2731                     return new Exports(ms, source, targets, true);
2732                 }
2733 
2734                 @Override
2735                 public Opens newOpens(Set<Opens.Modifier> ms,
2736                                       String source,
2737                                       Set<String> targets) {
2738                     return new Opens(ms, source, targets, true);
2739                 }
2740 
2741                 @Override
2742                 public Opens newOpens(Set<Opens.Modifier> ms, String source) {
2743                     return new Opens(ms, source, Collections.emptySet(), true);
2744                 }
2745 
2746                 @Override
2747                 public Provides newProvides(String service, List<String> providers) {
2748                     return new Provides(service, providers, true);
2749                 }
2750 
2751                 @Override











2752                 public ModuleDescriptor newModuleDescriptor(String name,
2753                                                             Version version,
2754                                                             Set<ModuleDescriptor.Modifier> modifiers,


2755                                                             Set<Requires> requires,
2756                                                             Set<Exports> exports,
2757                                                             Set<Opens> opens,
2758                                                             Set<String> uses,
2759                                                             Set<Provides> provides,
2760                                                             Set<String> packages,
2761                                                             String mainClass,
2762                                                             String osName,
2763                                                             String osArch,
2764                                                             String osVersion,
2765                                                             int hashCode) {
2766                     return new ModuleDescriptor(name,
2767                                                 version,
2768                                                 modifiers,


2769                                                 requires,
2770                                                 exports,
2771                                                 opens,
2772                                                 uses,
2773                                                 provides,
2774                                                 packages,
2775                                                 mainClass,
2776                                                 osName,
2777                                                 osArch,
2778                                                 osVersion,
2779                                                 hashCode,
2780                                                 false);
2781                 }
2782 
2783                 @Override
2784                 public Configuration resolveAndBind(ModuleFinder finder,
2785                                                     Collection<String> roots,
2786                                                     boolean check,
2787                                                     PrintStream traceOutput)
2788                 {
2789                     return Configuration.resolveAndBind(finder, roots, check, traceOutput);
2790                 }
2791             });
2792     }
2793 
2794 }
< prev index next >