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