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 */ 112 SYNTHETIC, 113 114 /** 115 * The dependence was implicitly declared in the source of the module 116 * declaration. 117 */ 118 MANDATED; 119 120 } 121 122 private final Set<Modifier> mods; 123 private final String name; 124 private final Version compiledVersion; 125 126 private Requires(Set<Modifier> ms, String mn, Version v) { 127 if (ms.isEmpty()) { 128 ms = Collections.emptySet(); 129 } else { 130 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms)); 131 } 132 this.mods = ms; 133 this.name = mn; 134 this.compiledVersion = v; 135 } 136 137 private Requires(Set<Modifier> ms, String mn, Version v, boolean unused) { 138 this.mods = ms; 139 this.name = mn; 140 this.compiledVersion = v; 141 } 142 143 /** 144 * Returns the set of modifiers. 145 * 146 * @return A possibly-empty unmodifiable set of modifiers 147 */ 148 public Set<Modifier> modifiers() { 149 return mods; 150 } 151 152 /** 153 * Return the module name. 154 * 155 * @return The module name 156 */ 157 public String name() { 158 return name; 159 } 160 161 /** 162 * 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 */ 242 @Override 243 public boolean equals(Object ob) { 244 if (!(ob instanceof Requires)) 245 return false; 246 Requires that = (Requires)ob; 247 return name.equals(that.name) && mods.equals(that.mods) 248 && Objects.equals(compiledVersion, that.compiledVersion); 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 320 321 /** 322 * Constructs an export 323 */ 324 private Exports(Set<Modifier> ms, String source, Set<String> targets) { 325 if (ms.isEmpty()) { 326 ms = Collections.emptySet(); 327 } else { 328 ms = Collections.unmodifiableSet(EnumSet.copyOf(ms)); 329 } 330 this.mods = ms; 331 this.source = source; 332 this.targets = emptyOrUnmodifiableSet(targets); 333 } 334 335 private Exports(Set<Modifier> ms, 336 String source, 337 Set<String> targets, 338 boolean unused) { 339 this.mods = ms; 340 this.source = source; 341 this.targets = targets; 342 } 343 344 /** 345 * Returns the set of modifiers. 346 * 347 * @return A possibly-empty unmodifiable set of modifiers 348 */ 349 public Set<Modifier> modifiers() { 350 return mods; 351 } 352 353 /** 354 * Returns {@code true} if this is a qualified export. 355 * 356 * @return {@code true} if this is a qualified export 357 */ 358 public boolean isQualified() { 359 return !targets.isEmpty(); 360 } 361 362 /** 363 * Returns the package name. 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 404 * returns {@code false}. Two module exports objects are equal if their 405 * set of modifiers is equal, the package names are equal and the set 406 * of target module names is equal. </p> 407 * 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; 495 this.targets = emptyOrUnmodifiableSet(targets); 496 } 497 498 private Opens(Set<Modifier> ms, 499 String source, 500 Set<String> targets, 501 boolean unused) { 502 this.mods = ms; 503 this.source = source; 504 this.targets = targets; 505 } 506 507 /** 508 * Returns the set of modifiers. 509 * 510 * @return A possibly-empty unmodifiable set of modifiers 511 */ 512 public Set<Modifier> modifiers() { 513 return mods; 514 } 515 516 /** 517 * Returns {@code true} if this is a qualified opens. 518 * 519 * @return {@code true} if this is a qualified opens 520 */ 521 public boolean isQualified() { 522 return !targets.isEmpty(); 523 } 524 525 /** 526 * Returns the package name. 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 567 * returns {@code false}. Two {@code Opens} objects are equal if their 568 * set of modifiers is equal, the package names are equal and the set 569 * of target module names is equal. </p> 570 * 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 * 665 * <p> This method satisfies the general contract of the {@link 666 * java.lang.Object#equals(Object) Object.equals} method. </p> 667 * 668 * @param ob 669 * the object to which this object is to be compared 670 * 671 * @return {@code true} if, and only if, the given object is a 672 * {@code Provides} that is equal to this {@code Provides} 673 */ 674 @Override 675 public boolean equals(Object ob) { 676 if (!(ob instanceof Provides)) 677 return false; 678 Provides other = (Provides)ob; 679 return Objects.equals(this.service, other.service) && 680 Objects.equals(this.providers, other.providers); 681 } 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) { 763 char c = s.charAt(i); 764 int d = (c - '0'); 765 int n = s.length(); 766 while (++i < n) { 767 c = s.charAt(i); 768 if (c >= '0' && c <= '9') { 769 d = d * 10 + (c - '0'); 770 continue; 771 } 772 break; 773 } 774 acc.add(d); 775 return i; 776 } 777 778 // Take a string token starting at position i 779 // Append it to the given list 780 // Return the index of the first character not taken 781 // Requires: s.charAt(i) is not '.' 782 // 783 private static int takeString(String s, int i, List<Object> acc) { 784 int b = i; 785 int n = s.length(); 786 while (++i < n) { 787 char c = s.charAt(i); 788 if (c != '.' && c != '-' && c != '+' && !(c >= '0' && c <= '9')) 789 continue; 790 break; 791 } 792 acc.add(s.substring(b, i)); 793 return i; 794 } 795 796 // Syntax: tok+ ( '-' tok+)? ( '+' tok+)? 797 // First token string is sequence, second is pre, third is build 798 // Tokens are separated by '.' or '-', or by changes between alpha & numeric 799 // Numeric tokens are compared as decimal integers 800 // Non-numeric tokens are compared lexicographically 801 // A version with a non-empty pre is less than a version with same seq but no pre 802 // Tokens in build may contain '-' and '+' 803 // 804 private Version(String v) { 805 806 if (v == null) 807 throw new IllegalArgumentException("Null version string"); 808 int n = v.length(); 809 if (n == 0) 810 throw new IllegalArgumentException("Empty version string"); 811 812 int i = 0; 813 char c = v.charAt(i); 814 if (!(c >= '0' && c <= '9')) 815 throw new IllegalArgumentException(v 816 + ": Version string does not start" 817 + " with a number"); 818 819 List<Object> sequence = new ArrayList<>(4); 820 List<Object> pre = new ArrayList<>(2); 821 List<Object> build = new ArrayList<>(2); 822 823 i = takeNumber(v, i, sequence); 824 825 while (i < n) { 826 c = v.charAt(i); 827 if (c == '.') { 828 i++; 829 continue; 830 } 831 if (c == '-' || c == '+') { 832 i++; 833 break; 834 } 835 if (c >= '0' && c <= '9') 836 i = takeNumber(v, i, sequence); 837 else 838 i = takeString(v, i, sequence); 839 } 840 841 if (c == '-' && i >= n) 842 throw new IllegalArgumentException(v + ": Empty pre-release"); 843 844 while (i < n) { 845 c = v.charAt(i); 846 if (c >= '0' && c <= '9') 847 i = takeNumber(v, i, pre); 848 else 849 i = takeString(v, i, pre); 850 if (i >= n) 851 break; 852 c = v.charAt(i); 853 if (c == '.' || c == '-') { 854 i++; 855 continue; 856 } 857 if (c == '+') { 858 i++; 859 break; 860 } 861 } 862 863 if (c == '+' && i >= n) 864 throw new IllegalArgumentException(v + ": Empty pre-release"); 865 866 while (i < n) { 867 c = v.charAt(i); 868 if (c >= '0' && c <= '9') 869 i = takeNumber(v, i, build); 870 else 871 i = takeString(v, i, build); 872 if (i >= n) 873 break; 874 c = v.charAt(i); 875 if (c == '.' || c == '-' || c == '+') { 876 i++; 877 continue; 878 } 879 } 880 881 this.version = v; 882 this.sequence = sequence; 883 this.pre = pre; 884 this.build = build; 885 } 886 887 /** 888 * Parses the given string as a version string. 889 * 890 * @param v 891 * The string to parse 892 * 893 * @return The resulting {@code Version} 894 * 895 * @throws IllegalArgumentException 896 * If {@code v} is {@code null}, an empty string, or cannot be 897 * parsed as a version string 898 */ 899 public static Version parse(String v) { 900 return new Version(v); 901 } 902 903 @SuppressWarnings("unchecked") 904 private int cmp(Object o1, Object o2) { 905 return ((Comparable)o1).compareTo(o2); 906 } 907 908 private int compareTokens(List<Object> ts1, List<Object> ts2) { 909 int n = Math.min(ts1.size(), ts2.size()); 910 for (int i = 0; i < n; i++) { 911 Object o1 = ts1.get(i); 912 Object o2 = ts2.get(i); 913 if ((o1 instanceof Integer && o2 instanceof Integer) 914 || (o1 instanceof String && o2 instanceof String)) 915 { 916 int c = cmp(o1, o2); 917 if (c == 0) 918 continue; 919 return c; 920 } 921 // Types differ, so convert number to string form 922 int c = o1.toString().compareTo(o2.toString()); 923 if (c == 0) 924 continue; 925 return c; 926 } 927 List<Object> rest = ts1.size() > ts2.size() ? ts1 : ts2; 928 int e = rest.size(); 929 for (int i = n; i < e; i++) { 930 Object o = rest.get(i); 931 if (o instanceof Integer && ((Integer)o) == 0) 932 continue; 933 return ts1.size() - ts2.size(); 934 } 935 return 0; 936 } 937 938 /** 939 * Compares this module version to another module version. Module 940 * versions are compared as described in the class description. 941 * 942 * @param that 943 * The module version to compare 944 * 945 * @return A negative integer, zero, or a positive integer as this 946 * module version is less than, equal to, or greater than the 947 * given module version 948 */ 949 @Override 950 public int compareTo(Version that) { 951 int c = compareTokens(this.sequence, that.sequence); 952 if (c != 0) return c; 953 if (this.pre.isEmpty()) { 954 if (!that.pre.isEmpty()) return +1; 955 } else { 956 if (that.pre.isEmpty()) return -1; 957 } 958 c = compareTokens(this.pre, that.pre); 959 if (c != 0) return c; 960 return compareTokens(this.build, that.build); 961 } 962 963 /** 964 * Tests this module version for equality with the given object. 965 * 966 * <p> If the given object is not a {@code Version} then this method 967 * returns {@code false}. Two module version are equal if their 968 * corresponding components are equal. </p> 969 * 970 * <p> This method satisfies the general contract of the {@link 971 * java.lang.Object#equals(Object) Object.equals} method. </p> 972 * 973 * @param ob 974 * the object to which this object is to be compared 975 * 976 * @return {@code true} if, and only if, the given object is a module 977 * reference that is equal to this module reference 978 */ 979 @Override 980 public boolean equals(Object ob) { 981 if (!(ob instanceof Version)) 982 return false; 983 return compareTo((Version)ob) == 0; 984 } 985 986 /** 987 * Computes a hash code for this module version. 988 * 989 * <p> The hash code is based upon the components of the version and 990 * satisfies the general contract of the {@link Object#hashCode 991 * Object.hashCode} method. </p> 992 * 993 * @return The hash-code value for this module version 994 */ 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 }