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