1 /* 2 * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.module; 27 28 import java.io.InputStream; 29 import java.io.IOException; 30 import java.io.UncheckedIOException; 31 import java.nio.ByteBuffer; 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.EnumSet; 35 import java.util.HashMap; 36 import java.util.HashSet; 37 import java.util.List; 38 import java.util.Map; 39 import java.util.Objects; 40 import java.util.Optional; 41 import java.util.Set; 42 import java.util.function.Supplier; 43 44 import static jdk.internal.module.Checks.*; 45 import static java.util.Objects.*; 46 47 import jdk.internal.module.Checks; 48 import jdk.internal.module.Hasher.DependencyHashes; 49 50 51 /** 52 * A module descriptor. 53 * 54 * <p> A {@code ModuleDescriptor} is typically created from the binary form 55 * of a module declaration. The associated {@link ModuleDescriptor.Builder} 56 * class can also be used to create a {@code ModuleDescriptor} from its 57 * components. </p> 58 * 59 * <p> {@code ModuleDescriptor} objects are immutable and safe for use by 60 * multiple concurrent threads.</p> 61 * 62 * @since 9 63 * @see java.lang.reflect.Module 64 */ 65 66 public class ModuleDescriptor 67 implements Comparable<ModuleDescriptor> 68 { 69 70 /** 71 * <p> A dependence upon a module </p> 72 * 73 * @see ModuleDescriptor#requires() 74 * @since 9 75 */ 76 77 public final static class Requires 78 implements Comparable<Requires> 79 { 80 81 /** 82 * A modifier on a module dependence. 83 * 84 * @since 9 85 */ 86 public static enum Modifier { 87 88 /** 89 * The dependence causes any module which depends on the <i>current 90 * module</i> to have an implicitly declared dependence on the module 91 * named by the {@code Requires}. 92 */ 93 PUBLIC, 94 95 /** 96 * The dependence was not explicitly or implicitly declared in the 97 * source of the module declaration. 98 */ 99 SYNTHETIC, 100 101 /** 102 * The dependence was implicitly declared in the source of the module 103 * declaration. 104 */ 105 MANDATED; 106 107 } 108 109 private final Set<Modifier> mods; 110 private final String name; 111 112 private Requires(Set<Modifier> ms, String mn) { 113 this(ms, mn, true); 114 } 115 private Requires(Set<Modifier> ms, String mn, boolean check) { 116 if (ms == null || ms.isEmpty()) { 117 mods = Collections.emptySet(); 118 } else { 119 mods = check ? Collections.unmodifiableSet(EnumSet.copyOf(ms)) 120 : ms; 121 } 122 this.name = check ? requireModuleName(mn) : mn; 123 } 124 125 /** 126 * Returns the set of modifiers. 127 * 128 * @return A possibly-empty unmodifiable set of modifiers 129 */ 130 public Set<Modifier> modifiers() { 131 return mods; 132 } 133 134 /** 135 * Return the module name. 136 * 137 * @return The module name 138 */ 139 public String name() { 140 return name; 141 } 142 143 /** 144 * Compares this module dependence to another. 145 * 146 * <p> Two {@code Requires} objects are compared by comparing their 147 * module name lexicographically. Where the module names are equal then 148 * the sets of modifiers are compared. 149 * 150 * @return A negative integer, zero, or a positive integer if this module 151 * dependence is less than, equal to, or greater than the given 152 * module dependence 153 */ 154 @Override 155 public int compareTo(Requires that) { 156 int c = this.name().compareTo(that.name()); 157 if (c != 0) 158 return c; 159 // same name, compare by modifiers 160 return Long.compare(this.modsValue(), that.modsValue()); 161 } 162 163 /** 164 * Return a value for the modifiers to allow sets of modifiers to be 165 * compared. 166 */ 167 private long modsValue() { 168 long value = 0; 169 for (Modifier m : mods) { 170 value += 1 << m.ordinal(); 171 } 172 return value; 173 } 174 175 176 @Override 177 public boolean equals(Object ob) { 178 if (!(ob instanceof Requires)) 179 return false; 180 Requires that = (Requires)ob; 181 return (name.equals(that.name) && mods.equals(that.mods)); 182 } 183 184 @Override 185 public int hashCode() { 186 return name.hashCode() * 43 + mods.hashCode(); 187 } 188 189 @Override 190 public String toString() { 191 return Dependence.toString(mods, name); 192 } 193 194 } 195 196 197 198 /** 199 * <p> A module export, may be qualified or unqualified. </p> 200 * 201 * @see ModuleDescriptor#exports() 202 * @since 9 203 */ 204 205 public final static class Exports { 206 207 private final String source; 208 private final Set<String> targets; // empty if unqualified export 209 210 /** 211 * Constructs a qualified export. 212 */ 213 private Exports(String source, Set<String> targets) { 214 this(source, targets, true); 215 } 216 217 private Exports(String source, Set<String> targets, boolean check) { 218 this.source = check ? requirePackageName(source) : source; 219 targets = check ? Collections.unmodifiableSet(new HashSet<>(targets)) 220 : Collections.unmodifiableSet(targets); 221 if (targets.isEmpty()) 222 throw new IllegalArgumentException("Empty target set"); 223 if (check) 224 targets.stream().forEach(Checks::requireModuleName); 225 this.targets = targets; 226 } 227 228 /** 229 * Constructs an unqualified export. 230 */ 231 private Exports(String source) { 232 this(source, true); 233 } 234 private Exports(String source, boolean check) { 235 this.source = check ? requirePackageName(source) : source; 236 this.targets = Collections.emptySet(); 237 } 238 239 /** 240 * Returns {@code true} if this is a qualified export. 241 * 242 * @return {@code true} if this is a qualified export 243 */ 244 public boolean isQualified() { 245 return !targets.isEmpty(); 246 } 247 248 /** 249 * Returns the package name. 250 * 251 * @return The package name 252 */ 253 public String source() { 254 return source; 255 } 256 257 /** 258 * For a qualified export, returns the non-empty and immutable set 259 * of the module names to which the package is exported. For an 260 * unqualified export, returns an empty set. 261 * 262 * @return The set of target module names or for an unqualified 263 * export, an empty set 264 */ 265 public Set<String> targets() { 266 return targets; 267 } 268 269 public int hashCode() { 270 return hash(source, targets); 271 } 272 273 public boolean equals(Object obj) { 274 if (!(obj instanceof Exports)) 275 return false; 276 Exports other = (Exports)obj; 277 return Objects.equals(this.source, other.source) && 278 Objects.equals(this.targets, other.targets); 279 } 280 281 public String toString() { 282 if (targets.isEmpty()) 283 return source; 284 else 285 return source + " to " + targets; 286 } 287 288 } 289 290 291 292 /** 293 * <p> A service that a module provides one or more implementations of. </p> 294 * 295 * @see ModuleDescriptor#provides() 296 * @since 9 297 */ 298 299 public final static class Provides { 300 301 private final String service; 302 private final Set<String> providers; 303 304 private Provides(String service, Set<String> providers) { 305 this(service, providers, true); 306 } 307 308 private Provides(String service, Set<String> providers, boolean check) { 309 this.service = check ? requireServiceTypeName(service) : service; 310 providers = check ? Collections.unmodifiableSet(new HashSet<>(providers)) 311 : Collections.unmodifiableSet(providers); 312 if (providers.isEmpty()) 313 throw new IllegalArgumentException("Empty providers set"); 314 if (check) 315 providers.forEach(Checks::requireServiceProviderName); 316 this.providers = providers; 317 } 318 319 /** 320 * Returns the fully qualified class name of the service type. 321 * 322 * @return The fully qualified class name of the service type. 323 */ 324 public String service() { return service; } 325 326 /** 327 * Returns the set of the fully qualified class names of the providers. 328 * 329 * @return A non-empty and unmodifiable set of the fully qualified class 330 * names of the providers. 331 */ 332 public Set<String> providers() { return providers; } 333 334 public int hashCode() { 335 return hash(service, providers); 336 } 337 338 public boolean equals(Object obj) { 339 if (!(obj instanceof Provides)) 340 return false; 341 Provides other = (Provides)obj; 342 return Objects.equals(this.service, other.service) && 343 Objects.equals(this.providers, other.providers); 344 } 345 346 } 347 348 349 350 /** 351 * Vaguely Debian-like version strings, for now. 352 * This will, eventually, change. 353 * 354 * @see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version">Debian 355 * Policy Manual, Chapter 5: Control files and their fields</a> 356 * 357 * @see ModuleDescriptor#version() 358 * @since 9 359 */ 360 361 public final static class Version 362 implements Comparable<Version> 363 { 364 365 private final String version; 366 367 // If Java had disjunctive types then we'd write List<Integer|String> here 368 // 369 private final List<Object> sequence; 370 private final List<Object> branch; 371 372 // Take a numeric token starting at position i 373 // Append it to the given list 374 // Return the index of the first character not taken 375 // Requires: s.charAt(i) is (decimal) numeric 376 // 377 private static int takeNumber(String s, int i, List<Object> acc) { 378 char c = s.charAt(i); 379 int d = (c - '0'); 380 int n = s.length(); 381 while (++i < n) { 382 c = s.charAt(i); 383 if (c >= '0' && c <= '9') { 384 d = d * 10 + (c - '0'); 385 continue; 386 } 387 break; 388 } 389 acc.add(d); 390 return i; 391 } 392 393 // Take a string token starting at position i 394 // Append it to the given list 395 // Return the index of the first character not taken 396 // Requires: s.charAt(i) is not '.' 397 // 398 private static int takeString(String s, int i, List<Object> acc) { 399 int b = i; 400 int n = s.length(); 401 while (++i < n) { 402 char c = s.charAt(i); 403 if (c != '.' && c != '-' && !(c >= '0' && c <= '9')) 404 continue; 405 break; 406 } 407 acc.add(s.substring(b, i)); 408 return i; 409 } 410 411 // Version syntax, for now: tok+ ( '-' tok+)? 412 // First token string is sequence, second is branch 413 // Tokens are delimited by '.', or by changes between alpha & numeric 414 // chars 415 // Numeric tokens are compared as decimal numbers 416 // Non-numeric tokens are compared lexicographically 417 // Tokens in branch may contain '-' 418 // 419 private Version(String v) { 420 421 if (v == null) 422 throw new IllegalArgumentException("Null version string"); 423 int n = v.length(); 424 if (n == 0) 425 throw new IllegalArgumentException("Empty version string"); 426 427 int i = 0; 428 char c = v.charAt(i); 429 if (!(c >= '0' && c <= '9')) 430 throw new 431 IllegalArgumentException(v 432 + ": Version does not start" 433 + " with a number"); 434 435 List<Object> sequence = new ArrayList<>(4); 436 List<Object> branch = new ArrayList<>(2); 437 438 i = takeNumber(v, i, sequence); 439 440 while (i < n) { 441 c = v.charAt(i); 442 if (c == '.') { 443 i++; 444 continue; 445 } 446 if (c == '-') { 447 i++; 448 break; 449 } 450 if (c >= '0' && c <= '9') 451 i = takeNumber(v, i, sequence); 452 else 453 i = takeString(v, i, sequence); 454 } 455 456 if (c == '-' && i >= n) 457 throw new IllegalArgumentException(v + ": Empty branch"); 458 459 while (i < n) { 460 c = v.charAt(i); 461 if (c >= '0' && c <= '9') 462 i = takeNumber(v, i, branch); 463 else 464 i = takeString(v, i, branch); 465 if (i >= n) 466 break; 467 c = v.charAt(i); 468 if (c == '.') { 469 i++; 470 continue; 471 } 472 } 473 474 this.version = v; 475 this.sequence = sequence; 476 this.branch = branch; 477 } 478 479 /** 480 * Parses the given string as a version string. 481 * 482 * @param v 483 * The string to parse as a version string 484 * 485 * @return The resulting {@code Version} 486 * 487 * @throws IllegalArgumentException 488 * If {@code v} is {@code null}, an empty string, or cannot be 489 * parsed as a version string 490 */ 491 public static Version parse(String v) { 492 return new Version(v); 493 } 494 495 @SuppressWarnings("unchecked") 496 private int cmp(Object o1, Object o2) { 497 return ((Comparable)o1).compareTo(o2); 498 } 499 500 private int compareTokens(List<Object> ts1, List<Object> ts2) { 501 int n = Math.min(ts1.size(), ts2.size()); 502 for (int i = 0; i < n; i++) { 503 Object o1 = ts1.get(i); 504 Object o2 = ts2.get(i); 505 if ( (o1 instanceof Integer && o2 instanceof Integer) 506 || (o1 instanceof String && o2 instanceof String)) { 507 int c = cmp(o1, o2); 508 if (c == 0) 509 continue; 510 return c; 511 } 512 // Types differ, so convert number to string form 513 int c = o1.toString().compareTo(o2.toString()); 514 if (c == 0) 515 continue; 516 return c; 517 } 518 List<Object> rest = ts1.size() > ts2.size() ? ts1 : ts2; 519 int e = rest.size(); 520 for (int i = n; i < e; i++) { 521 Object o = rest.get(i); 522 if (o instanceof Integer && ((Integer)o) == 0) 523 continue; 524 return ts1.size() - ts2.size(); 525 } 526 return 0; 527 } 528 529 @Override 530 public int compareTo(Version that) { 531 int c = compareTokens(this.sequence, that.sequence); 532 if (c != 0) 533 return c; 534 return compareTokens(this.branch, that.branch); 535 } 536 537 @Override 538 public boolean equals(Object ob) { 539 if (!(ob instanceof Version)) 540 return false; 541 return compareTo((Version)ob) == 0; 542 } 543 544 @Override 545 public int hashCode() { 546 return version.hashCode(); 547 } 548 549 @Override 550 public String toString() { 551 return version; 552 } 553 554 } 555 556 557 558 // From module declarations 559 private final String name; 560 private final Set<Requires> requires; 561 private final Set<Exports> exports; 562 private final Set<String> uses; 563 private final Map<String, Provides> provides; 564 565 // Indicates if synthesised for a JAR file found on the module path 566 private final boolean automatic; 567 568 // Not generated from a module-info.java 569 private final boolean synthetic; 570 571 // "Extended" information, added post-compilation by tools 572 private final Version version; 573 private final String mainClass; 574 private final String osName; 575 private final String osArch; 576 private final String osVersion; 577 private final Set<String> conceals; 578 private final Set<String> packages; 579 private final DependencyHashes hashes; 580 581 private ModuleDescriptor(String name, 582 boolean automatic, 583 boolean synthetic, 584 Map<String, Requires> requires, 585 Set<String> uses, 586 Map<String, Exports> exports, 587 Map<String, Provides> provides, 588 Version version, 589 String mainClass, 590 String osName, 591 String osArch, 592 String osVersion, 593 Set<String> conceals, 594 DependencyHashes hashes) 595 { 596 597 this.name = name; 598 this.automatic = automatic; 599 this.synthetic = synthetic; 600 601 Set<Requires> rqs = new HashSet<>(requires.values()); 602 assert (rqs.stream().map(Requires::name).sorted().distinct().count() 603 == rqs.size()) 604 : "Module " + name + " has duplicate requires"; 605 this.requires = emptyOrUnmodifiableSet(rqs); 606 607 Set<Exports> exs = new HashSet<>(exports.values()); 608 assert (exs.stream().map(Exports::source).sorted().distinct().count() 609 == exs.size()) 610 : "Module " + name + " has duplicate exports"; 611 this.exports = emptyOrUnmodifiableSet(exs); 612 613 this.uses = emptyOrUnmodifiableSet(uses); 614 this.provides = emptyOrUnmodifiableMap(provides); 615 616 this.version = version; 617 this.mainClass = mainClass; 618 this.osName = osName; 619 this.osArch = osArch; 620 this.osVersion = osVersion; 621 this.hashes = hashes; 622 623 assert !exports.keySet().stream().anyMatch(conceals::contains) 624 : "Module " + name + ": Package sets overlap"; 625 this.conceals = emptyOrUnmodifiableSet(conceals); 626 this.packages = computePackages(this.exports, this.conceals); 627 } 628 629 /** 630 * Clones the given module descriptor with an augmented set of packages 631 */ 632 ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) { 633 this.name = md.name; 634 this.automatic = md.automatic; 635 this.synthetic = md.synthetic; 636 637 this.requires = md.requires; 638 this.exports = md.exports; 639 this.uses = md.uses; 640 this.provides = md.provides; 641 642 this.version = md.version; 643 this.mainClass = md.mainClass; 644 this.osName = md.osName; 645 this.osArch = md.osArch; 646 this.osVersion = md.osVersion; 647 this.hashes = null; // need to ignore 648 649 this.packages = emptyOrUnmodifiableSet(pkgs); 650 this.conceals = computeConcealedPackages(this.exports, this.packages); 651 } 652 653 /** 654 * Creates a module descriptor from its components. This method is intended 655 * for use by the jlink plugin. 656 */ 657 ModuleDescriptor(String name, 658 boolean automatic, 659 boolean synthetic, 660 Set<Requires> requires, 661 Set<String> uses, 662 Set<Exports> exports, 663 Map<String, Provides> provides, 664 Version version, 665 String mainClass, 666 String osName, 667 String osArch, 668 String osVersion, 669 Set<String> conceals, 670 Set<String> packages) { 671 this.name = name; 672 this.automatic = automatic; 673 this.synthetic = synthetic; 674 this.requires = Collections.unmodifiableSet(requires); 675 this.exports = Collections.unmodifiableSet(exports); 676 this.uses = Collections.unmodifiableSet(uses); 677 this.provides = Collections.unmodifiableMap(provides); 678 this.conceals = Collections.unmodifiableSet(conceals); 679 this.packages = Collections.unmodifiableSet(packages); 680 681 this.version = version; 682 this.mainClass = mainClass; 683 this.osName = osName; 684 this.osArch = osArch; 685 this.osVersion = osVersion; 686 this.hashes = null; 687 } 688 689 /** 690 * <p> The module name. </p> 691 * 692 * @return The module name 693 */ 694 public String name() { 695 return name; 696 } 697 698 /** 699 * <p> Returns {@code true} if this is an automatic module. </p> 700 * 701 * <p> An automatic module is defined implicitly rather than explicitly 702 * and therefore does not have a module declaration. JAR files located on 703 * the application module path, or by the {@link ModuleFinder} returned by 704 * {@link ModuleFinder#of(java.nio.file.Path[]) ModuleFinder.of}, are 705 * treated as automatic modules if they do have not have a module 706 * declaration. </p> 707 * 708 * @return {@code true} if this is an automatic module 709 */ 710 public boolean isAutomatic() { 711 return automatic; 712 } 713 714 /** 715 * <p> Returns {@code true} if this module descriptor was not generated 716 * from an explicit module declaration ({@code module-info.java}) 717 * or an implicit module declaration (an {@link #isAutomatic() automatic} 718 * module). </p> 719 * 720 * @return {@code true} if this module descriptor was not generated by 721 * an explicit or implicit module declaration 722 * 723 * @jvms 4.7.8 The {@code Synthetic} Attribute 724 */ 725 public boolean isSynthetic() { 726 return synthetic; 727 } 728 729 /** 730 * <p> The dependences of this module. </p> 731 * 732 * @return A possibly-empty unmodifiable set of {@link Requires} objects 733 */ 734 public Set<Requires> requires() { 735 return requires; 736 } 737 738 /** 739 * <p> The service dependences of this module. </p> 740 * 741 * @return A possibly-empty unmodifiable set of the fully qualified class 742 * names of the service types used 743 */ 744 public Set<String> uses() { 745 return uses; 746 } 747 748 /** 749 * <p> The services that this module provides. </p> 750 * 751 * @return The possibly-empty unmodifiable map of the services that this 752 * module provides. The map key is fully qualified class name of 753 * the service type. 754 */ 755 public Map<String, Provides> provides() { 756 return provides; 757 } 758 759 /** 760 * <p> The module exports. </p> 761 * 762 * @return A possibly-empty unmodifiable set of exported packages 763 */ 764 public Set<Exports> exports() { 765 return exports; 766 } 767 768 /** 769 * Returns this module's version. 770 * 771 * @return This module's version 772 */ 773 public Optional<Version> version() { 774 return Optional.ofNullable(version); 775 } 776 777 /** 778 * Returns a string containing this module's name and, if present, its 779 * version. 780 * 781 * @return A string containing this module's name and, if present, its 782 * version. 783 */ 784 public String toNameAndVersion() { 785 if (version != null) { 786 return name() + "@" + version; 787 } else { 788 return name(); 789 } 790 } 791 792 /** 793 * Returns the module's main class. 794 * 795 * @return The fully qualified class name of this module's main class 796 */ 797 public Optional<String> mainClass() { 798 return Optional.ofNullable(mainClass); 799 } 800 801 /** 802 * Returns the operating system name if this module is operating system 803 * specific. 804 * 805 * @return The operating system name or an empty {@code Optional} 806 * if this module is not operating system specific 807 */ 808 public Optional<String> osName() { 809 return Optional.ofNullable(osName); 810 } 811 812 /** 813 * Returns the operating system architecture if this module is operating 814 * system architecture specific. 815 * 816 * @return The operating system architecture or an empty {@code Optional} 817 * if this module is not operating system architecture specific 818 */ 819 public Optional<String> osArch() { 820 return Optional.ofNullable(osArch); 821 } 822 823 /** 824 * Returns the operating system version if this module is operating 825 * system version specific. 826 * 827 * @return The operating system version or an empty {@code Optional} 828 * if this module is not operating system version specific 829 */ 830 public Optional<String> osVersion() { 831 return Optional.ofNullable(osVersion); 832 } 833 834 /** 835 * Returns the names of the packages defined in, but not exported by, this 836 * module. 837 * 838 * @return A possibly-empty unmodifiable set of the concealed packages 839 */ 840 public Set<String> conceals() { 841 return conceals; 842 } 843 844 /** 845 * Returns the names of all the packages defined in this module, whether 846 * exported or concealed. 847 * 848 * @return A possibly-empty unmodifiable set of the all packages 849 */ 850 public Set<String> packages() { 851 return packages; 852 } 853 854 /** 855 * Returns the object with the hashes of the dependences. 856 */ 857 Optional<DependencyHashes> hashes() { 858 return Optional.ofNullable(hashes); 859 } 860 861 862 /** 863 * A builder used for building {@link ModuleDescriptor} objects. 864 * 865 * <p> Example usage: </p> 866 * 867 * <pre>{@code 868 * ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1") 869 * .requires("m2") 870 * .exports("p") 871 * .build(); 872 * }</pre> 873 * @since 9 874 */ 875 public static final class Builder { 876 877 final String name; 878 final boolean automatic; 879 boolean synthetic; 880 final Map<String, Requires> requires = new HashMap<>(); 881 final Set<String> uses = new HashSet<>(); 882 final Map<String, Exports> exports = new HashMap<>(); 883 final Map<String, Provides> provides = new HashMap<>(); 884 Set<String> conceals = Collections.emptySet(); 885 Version version; 886 String osName; 887 String osArch; 888 String osVersion; 889 String mainClass; 890 DependencyHashes hashes; 891 892 /** 893 * Initializes a new builder with the given module name. 894 * 895 * @param name 896 * The module name 897 * 898 * @throws IllegalArgumentException 899 * If the module name is {@code null} or is not a legal Java 900 * identifier 901 */ 902 public Builder(String name) { 903 this(name, false); 904 } 905 906 /* package */ Builder(String name, boolean automatic) { 907 this.name = requireModuleName(name); 908 this.automatic = automatic; 909 } 910 911 /** 912 * Adds a dependence on a module. 913 * 914 * @param req 915 * The dependence 916 * 917 * @return This builder 918 * 919 * @throws IllegalArgumentException 920 * If the dependence is on the module that this builder was 921 * initialized to build 922 * @throws IllegalStateException 923 * If the dependence on the module has already been declared 924 */ 925 public Builder requires(Requires req) { 926 String mn = req.name(); 927 if (name.equals(mn)) 928 throw new IllegalArgumentException("Dependence on self"); 929 if (requires.containsKey(mn)) 930 throw new IllegalStateException("Dependence upon " + mn 931 + " already declared"); 932 requires.put(mn, req); 933 return this; 934 } 935 936 /** 937 * Adds a dependence on a module with the given (and possibly empty) 938 * set of modifiers. 939 * 940 * @param mods 941 * The set of modifiers 942 * @param mn 943 * The module name 944 * 945 * @return This builder 946 * 947 * @throws IllegalArgumentException 948 * If the module name is {@code null}, is not a legal Java 949 * identifier, or is equal to the module name that this builder 950 * was initialized to build 951 * @throws IllegalStateException 952 * If the dependence on the module has already been declared 953 */ 954 public Builder requires(Set<Requires.Modifier> mods, String mn) { 955 if (name.equals(mn)) 956 throw new IllegalArgumentException("Dependence on self: " + mn); 957 if (requires.containsKey(mn)) 958 throw new IllegalStateException("Dependence upon " + mn 959 + " already declared"); 960 requires.put(mn, new Requires(mods, mn)); // checks mn 961 return this; 962 } 963 964 /** 965 * Adds a dependence on a module with an empty set of modifiers. 966 * 967 * @param mn 968 * The module name 969 * 970 * @return This builder 971 * 972 * @throws IllegalArgumentException 973 * If the module name is {@code null}, is not a legal Java 974 * identifier, or is equal to the module name that this builder 975 * was initialized to build 976 * @throws IllegalStateException 977 * If the dependence on the module has already been declared 978 */ 979 public Builder requires(String mn) { 980 return requires(EnumSet.noneOf(Requires.Modifier.class), mn); 981 } 982 983 /** 984 * Adds a dependence on a module with the given modifier. 985 * 986 * @param mod 987 * The modifier 988 * @param mn 989 * The module name 990 * 991 * @return This builder 992 * 993 * @throws IllegalArgumentException 994 * If the module name is {@code null}, is not a legal Java 995 * identifier, or is equal to the module name that this builder 996 * was initialized to build 997 * @throws IllegalStateException 998 * If the dependence on the module has already been declared 999 */ 1000 public Builder requires(Requires.Modifier mod, String mn) { 1001 return requires(EnumSet.of(mod), mn); 1002 } 1003 1004 /** 1005 * Adds a service dependence. 1006 * 1007 * @param st 1008 * The service type 1009 * 1010 * @return This builder 1011 * 1012 * @throws IllegalArgumentException 1013 * If the service type is {@code null} or is not a legal Java 1014 * identifier 1015 * @throws IllegalStateException 1016 * If a dependency on the service type has already been declared 1017 */ 1018 public Builder uses(String st) { 1019 if (uses.contains(requireServiceTypeName(st))) 1020 throw new IllegalStateException("Dependence upon service " 1021 + st + " already declared"); 1022 uses.add(st); 1023 return this; 1024 } 1025 1026 /** 1027 * Ensures that the given package name has not been declared as an 1028 * exported or concealed package. 1029 */ 1030 private void ensureNotExportedOrConcealed(String pn) { 1031 if (exports.containsKey(pn)) 1032 throw new IllegalStateException("Export of package " 1033 + pn + " already declared"); 1034 if (conceals.contains(pn)) 1035 throw new IllegalStateException("Concealed package " 1036 + pn + " already declared"); 1037 } 1038 1039 /** 1040 * Adds an export. 1041 * 1042 * @param e 1043 * The export 1044 * 1045 * @return This builder 1046 * 1047 * @throws IllegalStateException 1048 * If the package is already declared as an exported or 1049 * concealed package 1050 */ 1051 public Builder exports(Exports e) { 1052 String pn = e.source(); 1053 ensureNotExportedOrConcealed(pn); 1054 exports.put(pn, e); 1055 return this; 1056 } 1057 1058 /** 1059 * Adds an export to a set of target modules. 1060 * 1061 * @param pn 1062 * The package name 1063 * @param targets 1064 * The set of target modules names 1065 * 1066 * @return This builder 1067 * 1068 * @throws IllegalArgumentException 1069 * If the package name or any of the target modules is {@code 1070 * null} or is not a legal Java identifier, or the set of 1071 * targets is empty 1072 * @throws IllegalStateException 1073 * If the package is already declared as an exported or 1074 * concealed package 1075 */ 1076 public Builder exports(String pn, Set<String> targets) { 1077 ensureNotExportedOrConcealed(pn); 1078 exports.put(pn, new Exports(pn, targets)); // checks pn and targets 1079 return this; 1080 } 1081 1082 /** 1083 * Adds an export to a target module. 1084 * 1085 * @param pn 1086 * The package name 1087 * @param target 1088 * The target module name 1089 * 1090 * @return This builder 1091 * 1092 * @throws IllegalArgumentException 1093 * If the package name or target module is {@code null} or is 1094 * not a legal Java identifier 1095 * @throws IllegalStateException 1096 * If the package is already declared as an exported or 1097 * concealed package 1098 */ 1099 public Builder exports(String pn, String target) { 1100 return exports(pn, Collections.singleton(target)); 1101 } 1102 1103 /** 1104 * Adds an export. 1105 * 1106 * @param pn 1107 * The package name 1108 * 1109 * @return This builder 1110 * 1111 * @throws IllegalArgumentException 1112 * If the package name is {@code null} or is not a legal Java 1113 * identifier 1114 * @throws IllegalStateException 1115 * If the package is already declared as an exported or 1116 * concealed package 1117 */ 1118 public Builder exports(String pn) { 1119 ensureNotExportedOrConcealed(pn); 1120 exports.put(pn, new Exports(pn)); // checks pn 1121 return this; 1122 } 1123 1124 // Used by ModuleInfo, after a packageFinder is invoked 1125 /* package */ Set<String> exportedPackages() { 1126 return exports.keySet(); 1127 } 1128 1129 /** 1130 * Provides a service with one or more implementations. 1131 * 1132 * @param p 1133 * The provides 1134 * 1135 * @return This builder 1136 * 1137 * @throws IllegalStateException 1138 * If the providers for the service type have already been 1139 * declared 1140 */ 1141 public Builder provides(Provides p) { 1142 String st = p.service(); 1143 if (provides.containsKey(st)) 1144 throw new IllegalStateException("Providers of service " 1145 + st + " already declared"); 1146 provides.put(st, p); 1147 return this; 1148 } 1149 1150 /** 1151 * Provides service {@code st} with implementations {@code pcs}. 1152 * 1153 * @param st 1154 * The service type 1155 * @param pcs 1156 * The set of provider class names 1157 * 1158 * @return This builder 1159 * 1160 * @throws IllegalArgumentException 1161 * If the service type or any of the provider class names is 1162 * {@code null} or is not a legal Java identifier, or the set 1163 * of provider class names is empty 1164 * @throws IllegalStateException 1165 * If the providers for the service type have already been 1166 * declared 1167 */ 1168 public Builder provides(String st, Set<String> pcs) { 1169 if (provides.containsKey(st)) 1170 throw new IllegalStateException("Providers of service " 1171 + st + " already declared"); 1172 provides.put(st, new Provides(st, pcs)); // checks st and pcs 1173 return this; 1174 } 1175 1176 /** 1177 * Provides service {@code st} with implementation {@code pc}. 1178 * 1179 * @param st 1180 * The service type 1181 * @param pc 1182 * The provider class name 1183 * 1184 * @return This builder 1185 * 1186 * @throws IllegalArgumentException 1187 * If the service type or the provider class name is {@code 1188 * null} or is not a legal Java identifier 1189 * @throws IllegalStateException 1190 * If the providers for the service type have already been 1191 * declared 1192 */ 1193 public Builder provides(String st, String pc) { 1194 return provides(st, Collections.singleton(pc)); 1195 } 1196 1197 /** 1198 * Adds a set of (possible empty) concealed packages. 1199 * 1200 * @param pns 1201 * The set of package names of the concealed packages 1202 * 1203 * @return This builder 1204 * 1205 * @throws IllegalArgumentException 1206 * If any of the package names is {@code null} or is not a 1207 * legal Java identifier 1208 * @throws IllegalStateException 1209 * If any of packages are already declared as a concealed or 1210 * exported package 1211 */ 1212 public Builder conceals(Set<String> pns) { 1213 pns.forEach(this::conceals); 1214 return this; 1215 } 1216 1217 /** 1218 * Adds a concealed package. 1219 * 1220 * @param pn 1221 * The package name 1222 * 1223 * @return This builder 1224 * 1225 * @throws IllegalArgumentException 1226 * If the package name is {@code null}, or is not a legal Java 1227 * identifier 1228 * @throws IllegalStateException 1229 * If the package is already declared as a concealed or exported 1230 * package 1231 */ 1232 public Builder conceals(String pn) { 1233 Checks.requirePackageName(pn); 1234 ensureNotExportedOrConcealed(pn); 1235 if (conceals.isEmpty()) 1236 conceals = new HashSet<>(); 1237 conceals.add(pn); 1238 return this; 1239 } 1240 1241 /** 1242 * Sets the module version. 1243 * 1244 * @param v 1245 * The version 1246 * 1247 * @return This builder 1248 * 1249 * @throws IllegalStateException 1250 * If the module version is already set 1251 */ 1252 public Builder version(Version v) { 1253 if (version != null) 1254 throw new IllegalStateException("module version already set"); 1255 version = requireNonNull(v); 1256 return this; 1257 } 1258 1259 /** 1260 * Sets the module version. 1261 * 1262 * @param v 1263 * The version string to parse 1264 * 1265 * @return This builder 1266 * 1267 * @throws IllegalArgumentException 1268 * If {@code v} is null or cannot be parsed as a version string 1269 * @throws IllegalStateException 1270 * If the module version is already set 1271 * 1272 * @see Version#parse(String) 1273 */ 1274 public Builder version(String v) { 1275 if (version != null) 1276 throw new IllegalStateException( 1277 "module version already set: " + version); 1278 version = Version.parse(v); 1279 return this; 1280 } 1281 1282 /** 1283 * Sets the module main class. 1284 * 1285 * @param mc 1286 * The module main class 1287 * 1288 * @return This builder 1289 * 1290 * @throws IllegalArgumentException 1291 * If {@code mainClass} is null or is not a legal Java identifier 1292 * @throws IllegalStateException 1293 * If the module main class is already set 1294 */ 1295 public Builder mainClass(String mc) { 1296 if (mainClass != null) 1297 throw new IllegalStateException( 1298 "main class already set: " + mainClass); 1299 mainClass = requireJavaIdentifier("main class name", mc); 1300 return this; 1301 } 1302 1303 /** 1304 * Sets the operating system name. 1305 * 1306 * @param name 1307 * The operating system name 1308 * 1309 * @return This builder 1310 * 1311 * @throws IllegalArgumentException 1312 * If {@code name} is null or the empty String 1313 * @throws IllegalStateException 1314 * If the operating system name is already set 1315 */ 1316 public Builder osName(String name) { 1317 if (osName != null) 1318 throw new IllegalStateException( 1319 "OS name already set: " + osName); 1320 if (name == null || name.isEmpty()) 1321 throw new IllegalArgumentException("OS name is null or empty"); 1322 osName = name; 1323 return this; 1324 } 1325 1326 /** 1327 * Sets the operating system architecture. 1328 * 1329 * @param arch 1330 * The operating system architecture 1331 * 1332 * @return This builder 1333 * 1334 * @throws IllegalArgumentException 1335 * If {@code name} is null or the empty String 1336 * @throws IllegalStateException 1337 * If the operating system architecture is already set 1338 */ 1339 public Builder osArch(String arch) { 1340 if (osArch != null) 1341 throw new IllegalStateException( 1342 "OS arch already set: " + osArch); 1343 if (arch == null || arch.isEmpty()) 1344 throw new IllegalArgumentException("OS arch is null or empty"); 1345 osArch = arch; 1346 return this; 1347 } 1348 1349 /** 1350 * Sets the operating system version. 1351 * 1352 * @param version 1353 * The operating system version 1354 * 1355 * @return This builder 1356 * 1357 * @throws IllegalArgumentException 1358 * If {@code name} is null or the empty String 1359 * @throws IllegalStateException 1360 * If the operating system version is already set 1361 */ 1362 public Builder osVersion(String version) { 1363 if (osVersion != null) 1364 throw new IllegalStateException( 1365 "OS version already set: " + osVersion); 1366 if (version == null || version.isEmpty()) 1367 throw new IllegalArgumentException("OS version is null or empty"); 1368 osVersion = version; 1369 return this; 1370 } 1371 1372 /* package */ Builder hashes(DependencyHashes hashes) { 1373 this.hashes = hashes; 1374 return this; 1375 } 1376 1377 1378 /* package */ Builder synthetic(boolean v) { 1379 this.synthetic = v; 1380 return this; 1381 } 1382 1383 /** 1384 * Builds and returns a {@code ModuleDescriptor} from its components. 1385 * 1386 * @return The module descriptor 1387 */ 1388 public ModuleDescriptor build() { 1389 assert name != null; 1390 1391 return new ModuleDescriptor(name, 1392 automatic, 1393 synthetic, 1394 requires, 1395 uses, 1396 exports, 1397 provides, 1398 version, 1399 mainClass, 1400 osName, 1401 osArch, 1402 osVersion, 1403 conceals, 1404 hashes); 1405 } 1406 1407 } 1408 1409 1410 /** 1411 * Compares this module descriptor to another. 1412 * 1413 * <p> Two {@code ModuleDescriptor} objects are compared by comparing their 1414 * module name lexicographically. Where the module names are equal then 1415 * the versions, if present, are compared. 1416 * 1417 * @param that 1418 * The object to which this module descriptor is to be compared 1419 * 1420 * @return A negative integer, zero, or a positive integer if this module 1421 * descriptor is less than, equal to, or greater than the given 1422 * module descriptor 1423 */ 1424 @Override 1425 public int compareTo(ModuleDescriptor that) { 1426 int c = this.name().compareTo(that.name()); 1427 if (c != 0) return c; 1428 if (version == null) { 1429 if (that.version == null) 1430 return 0; 1431 return -1; 1432 } 1433 if (that.version == null) 1434 return +1; 1435 return version.compareTo(that.version); 1436 } 1437 1438 @Override 1439 public boolean equals(Object ob) { 1440 if (ob == this) 1441 return true; 1442 if (!(ob instanceof ModuleDescriptor)) 1443 return false; 1444 ModuleDescriptor that = (ModuleDescriptor)ob; 1445 return (name.equals(that.name) 1446 && automatic == that.automatic 1447 && synthetic == that.synthetic 1448 && requires.equals(that.requires) 1449 && uses.equals(that.uses) 1450 && exports.equals(that.exports) 1451 && provides.equals(that.provides) 1452 && Objects.equals(version, that.version) 1453 && Objects.equals(mainClass, that.mainClass) 1454 && Objects.equals(osName, that.osName) 1455 && Objects.equals(osArch, that.osArch) 1456 && Objects.equals(osVersion, that.osVersion) 1457 && Objects.equals(conceals, that.conceals) 1458 && Objects.equals(hashes, that.hashes)); 1459 } 1460 1461 private transient int hash; // cached hash code 1462 1463 @Override 1464 public int hashCode() { 1465 int hc = hash; 1466 if (hc == 0) { 1467 hc = name.hashCode(); 1468 hc = hc * 43 + Boolean.hashCode(automatic); 1469 hc = hc * 43 + Boolean.hashCode(synthetic); 1470 hc = hc * 43 + requires.hashCode(); 1471 hc = hc * 43 + uses.hashCode(); 1472 hc = hc * 43 + exports.hashCode(); 1473 hc = hc * 43 + provides.hashCode(); 1474 hc = hc * 43 + Objects.hashCode(version); 1475 hc = hc * 43 + Objects.hashCode(mainClass); 1476 hc = hc * 43 + Objects.hashCode(osName); 1477 hc = hc * 43 + Objects.hashCode(osArch); 1478 hc = hc * 43 + Objects.hashCode(osVersion); 1479 hc = hc * 43 + Objects.hashCode(conceals); 1480 hc = hc * 43 + Objects.hashCode(hashes); 1481 if (hc != 0) hash = hc; 1482 } 1483 return hc; 1484 } 1485 1486 @Override 1487 public String toString() { 1488 StringBuilder sb = new StringBuilder(); 1489 sb.append("Module { name: ").append(toNameAndVersion()); 1490 if (!requires.isEmpty()) 1491 sb.append(", ").append(requires); 1492 if (!uses.isEmpty()) 1493 sb.append(", ").append(uses); 1494 if (!exports.isEmpty()) 1495 sb.append(", exports: ").append(exports); 1496 if (!provides.isEmpty()) { 1497 sb.append(", provides: ["); 1498 for (Map.Entry<String, Provides> entry : provides.entrySet()) { 1499 sb.append(entry.getKey()) 1500 .append(" with ") 1501 .append(entry.getValue()); 1502 } 1503 sb.append("]"); 1504 } 1505 sb.append(" }"); 1506 return sb.toString(); 1507 } 1508 1509 /** 1510 * Reads the binary form of a module declaration from an input stream 1511 * as a module descriptor. 1512 * 1513 * <p> If the descriptor encoded in the input stream does not indicate a 1514 * set of concealed packages then the {@code packageFinder} will be 1515 * invoked. The packages it returns, except for those indicated as 1516 * exported in the encoded descriptor, will be considered to be concealed. 1517 * If the {@code packageFinder} throws an {@link UncheckedIOException} then 1518 * {@link IOException} cause will be re-thrown. </p> 1519 * 1520 * <p> If there are bytes following the module descriptor then it is 1521 * implementation specific as to whether those bytes are read, ignored, 1522 * or reported as an {@code InvalidModuleDescriptorException}. If this 1523 * method fails with an {@code InvalidModuleDescriptorException} or {@code 1524 * IOException} then it may do so after some, but not all, bytes have 1525 * been read from the input stream. It is strongly recommended that the 1526 * stream be promptly closed and discarded if an exception occurs. </p> 1527 * 1528 * @apiNote The {@code packageFinder} parameter is for use when reading 1529 * module descriptors from legacy module-artifact formats that do not 1530 * record the set of concealed packages in the descriptor itself. 1531 * 1532 * @param in 1533 * The input stream 1534 * @param packageFinder 1535 * A supplier that can produce a set of package names 1536 * 1537 * @return The module descriptor 1538 * 1539 * @throws InvalidModuleDescriptorException 1540 * If an invalid module descriptor is detected 1541 * @throws IOException 1542 * If an I/O error occurs reading from the input stream or {@code 1543 * UncheckedIOException} is thrown by the package finder 1544 */ 1545 public static ModuleDescriptor read(InputStream in, 1546 Supplier<Set<String>> packageFinder) 1547 throws IOException 1548 { 1549 return ModuleInfo.read(in, requireNonNull(packageFinder)); 1550 } 1551 1552 /** 1553 * Reads the binary form of a module declaration from an input stream 1554 * as a module descriptor. 1555 * 1556 * @param in 1557 * The input stream 1558 * 1559 * @return The module descriptor 1560 * 1561 * @throws InvalidModuleDescriptorException 1562 * If an invalid module descriptor is detected 1563 * @throws IOException 1564 * If an I/O error occurs reading from the input stream 1565 */ 1566 public static ModuleDescriptor read(InputStream in) throws IOException { 1567 return ModuleInfo.read(in, null); 1568 } 1569 1570 /** 1571 * Reads the binary form of a module declaration from a byte buffer 1572 * as a module descriptor. 1573 * 1574 * <p> If the descriptor encoded in the byte buffer does not indicate a 1575 * set of concealed packages then the {@code packageFinder} will be 1576 * invoked. The packages it returns, except for those indicated as 1577 * exported in the encoded descriptor, will be considered to be 1578 * concealed. </p> 1579 * 1580 * <p> The module descriptor is read from the buffer stating at index 1581 * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position() 1582 * position} when this method is invoked. Upon return the buffer's position 1583 * will be equal to {@code p + n} where {@code n} is the number of bytes 1584 * read from the buffer. </p> 1585 * 1586 * <p> If there are bytes following the module descriptor then it is 1587 * implementation specific as to whether those bytes are read, ignored, 1588 * or reported as an {@code InvalidModuleDescriptorException}. If this 1589 * method fails with an {@code InvalidModuleDescriptorException} then it 1590 * may do so after some, but not all, bytes have been read. </p> 1591 * 1592 * @apiNote The {@code packageFinder} parameter is for use when reading 1593 * module descriptors from legacy module-artifact formats that do not 1594 * record the set of concealed packages in the descriptor itself. 1595 * 1596 * @param bb 1597 * The byte buffer 1598 * @param packageFinder 1599 * A supplier that can produce a set of package names 1600 * 1601 * @return The module descriptor 1602 * 1603 * @throws InvalidModuleDescriptorException 1604 * If an invalid module descriptor is detected 1605 */ 1606 public static ModuleDescriptor read(ByteBuffer bb, 1607 Supplier<Set<String>> packageFinder) 1608 { 1609 return ModuleInfo.read(bb, requireNonNull(packageFinder)); 1610 } 1611 1612 /** 1613 * Reads the binary form of a module declaration from a byte buffer 1614 * as a module descriptor. 1615 * 1616 * @param bb 1617 * The byte buffer 1618 * 1619 * @return The module descriptor 1620 * 1621 * @throws InvalidModuleDescriptorException 1622 * If an invalid module descriptor is detected 1623 */ 1624 public static ModuleDescriptor read(ByteBuffer bb) { 1625 return ModuleInfo.read(bb, null); 1626 } 1627 1628 1629 /** 1630 * Computes the set of packages from exports and concealed packages. 1631 * It returns the concealed packages set if there is no exported package. 1632 */ 1633 private static Set<String> computePackages(Set<Exports> exports, 1634 Set<String> conceals) 1635 { 1636 if (exports.isEmpty()) 1637 return conceals; 1638 1639 Set<String> pkgs = new HashSet<>(conceals); 1640 exports.stream().map(Exports::source).forEach(pkgs::add); 1641 return emptyOrUnmodifiableSet(pkgs); 1642 } 1643 1644 /** 1645 * Computes the set of concealed packages from exports and all packages. 1646 * It returns the packages set if there are no exported packages. 1647 */ 1648 private static Set<String> computeConcealedPackages(Set<Exports> exports, 1649 Set<String> pkgs) 1650 { 1651 if (exports.isEmpty()) 1652 return pkgs; 1653 1654 Set<String> conceals = new HashSet<>(pkgs); 1655 exports.stream().map(Exports::source).forEach(conceals::remove); 1656 return emptyOrUnmodifiableSet(conceals); 1657 } 1658 1659 private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) { 1660 if (map.isEmpty()) { 1661 return Collections.emptyMap(); 1662 } else if (map.size() == 1) { 1663 Map.Entry<K, V> entry = map.entrySet().iterator().next(); 1664 return Collections.singletonMap(entry.getKey(), entry.getValue()); 1665 } else { 1666 return Collections.unmodifiableMap(map); 1667 } 1668 } 1669 1670 private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) { 1671 if (set.isEmpty()) { 1672 return Collections.emptySet(); 1673 } else if (set.size() == 1) { 1674 return Collections.singleton(set.iterator().next()); 1675 } else { 1676 return Collections.unmodifiableSet(set); 1677 } 1678 } 1679 1680 static { 1681 /** 1682 * Setup the shared secret to allow code in other packages create 1683 * ModuleDescriptor and associated objects directly. 1684 */ 1685 jdk.internal.misc.SharedSecrets 1686 .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() { 1687 @Override 1688 public Requires newRequires(Set<Requires.Modifier> ms, String mn) { 1689 return new Requires(ms, mn, false); 1690 } 1691 1692 @Override 1693 public Exports newExports(String source, Set<String> targets) { 1694 return new Exports(source, targets, false); 1695 } 1696 1697 @Override 1698 public Exports newExports(String source) { 1699 return new Exports(source, false); 1700 } 1701 1702 @Override 1703 public Provides newProvides(String service, Set<String> providers) { 1704 return new Provides(service, providers, false); 1705 } 1706 1707 @Override 1708 public Version newVersion(String v) { 1709 return new Version(v); 1710 } 1711 1712 @Override 1713 public ModuleDescriptor newModuleDescriptor(ModuleDescriptor md, 1714 Set<String> pkgs) { 1715 return new ModuleDescriptor(md, pkgs); 1716 } 1717 1718 @Override 1719 public ModuleDescriptor newModuleDescriptor(String name, 1720 boolean automatic, 1721 boolean synthetic, 1722 Set<Requires> requires, 1723 Set<String> uses, Set<Exports> exports, 1724 Map<String, Provides> provides, 1725 Version version, 1726 String mainClass, 1727 String osName, 1728 String osArch, 1729 String osVersion, 1730 Set<String> conceals, 1731 Set<String> packages) { 1732 return new ModuleDescriptor(name, 1733 automatic, 1734 synthetic, 1735 requires, 1736 uses, 1737 exports, 1738 provides, 1739 version, 1740 mainClass, 1741 osName, 1742 osArch, 1743 osVersion, 1744 conceals, 1745 packages); 1746 } 1747 }); 1748 } 1749 1750 }