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