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