1 /* 2 * Copyright (c) 2015, 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 jdk.internal.module; 27 28 import java.lang.module.ModuleDescriptor; 29 import java.lang.module.ModuleDescriptor.Requires; 30 import java.lang.module.ModuleDescriptor.Exports; 31 import java.lang.module.ModuleDescriptor.Opens; 32 import java.lang.module.ModuleDescriptor.Provides; 33 import java.lang.module.ModuleDescriptor.Version; 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.HashMap; 37 import java.util.HashSet; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.Set; 41 42 import jdk.internal.misc.JavaLangModuleAccess; 43 import jdk.internal.misc.SharedSecrets; 44 import jdk.internal.org.objectweb.asm.Attribute; 45 import jdk.internal.org.objectweb.asm.ByteVector; 46 import jdk.internal.org.objectweb.asm.ClassReader; 47 import jdk.internal.org.objectweb.asm.ClassWriter; 48 import jdk.internal.org.objectweb.asm.Label; 49 import static jdk.internal.module.ClassFileConstants.*; 50 51 52 /** 53 * Provides ASM implementations of {@code Attribute} to read and write the 54 * class file attributes in a module-info class file. 55 */ 56 57 public final class ClassFileAttributes { 58 59 private ClassFileAttributes() { } 60 61 /** 62 * Module_attribute { 63 * // See lang-vm.html for details. 64 * } 65 */ 66 public static class ModuleAttribute extends Attribute { 67 private static final JavaLangModuleAccess JLMA 68 = SharedSecrets.getJavaLangModuleAccess(); 69 70 private ModuleDescriptor descriptor; 71 private Version replacementVersion; 72 73 public ModuleAttribute(ModuleDescriptor descriptor) { 74 super(MODULE); 75 this.descriptor = descriptor; 76 } 77 78 public ModuleAttribute(Version v) { 79 super(MODULE); 80 this.replacementVersion = v; 81 } 82 83 public ModuleAttribute() { 84 super(MODULE); 85 } 86 87 @Override 88 protected Attribute read(ClassReader cr, 89 int off, 90 int len, 91 char[] buf, 92 int codeOff, 93 Label[] labels) 94 { 95 // module_name (CONSTANT_Module_info) 96 String mn = cr.readModule(off, buf); 97 off += 2; 98 99 // module_flags 100 int module_flags = cr.readUnsignedShort(off); 101 boolean open = ((module_flags & ACC_OPEN) != 0); 102 boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0); 103 off += 2; 104 105 ModuleDescriptor.Builder builder = JLMA.newModuleBuilder(mn, 106 false, 107 open, 108 synthetic); 109 110 // module_version 111 String module_version = cr.readUTF8(off, buf); 112 off += 2; 113 if (replacementVersion != null) { 114 builder.version(replacementVersion); 115 } else if (module_version != null) { 116 builder.version(module_version); 117 } 118 119 // requires_count and requires[requires_count] 120 int requires_count = cr.readUnsignedShort(off); 121 off += 2; 122 for (int i=0; i<requires_count; i++) { 123 // CONSTANT_Module_info 124 String dn = cr.readModule(off, buf); 125 off += 2; 126 127 // requires_flags 128 int requires_flags = cr.readUnsignedShort(off); 129 off += 2; 130 Set<Requires.Modifier> mods; 131 if (requires_flags == 0) { 132 mods = Collections.emptySet(); 133 } else { 134 mods = new HashSet<>(); 135 if ((requires_flags & ACC_TRANSITIVE) != 0) 136 mods.add(Requires.Modifier.TRANSITIVE); 137 if ((requires_flags & ACC_STATIC_PHASE) != 0) 138 mods.add(Requires.Modifier.STATIC); 139 if ((requires_flags & ACC_SYNTHETIC) != 0) 140 mods.add(Requires.Modifier.SYNTHETIC); 141 if ((requires_flags & ACC_MANDATED) != 0) 142 mods.add(Requires.Modifier.MANDATED); 143 } 144 145 146 // requires_version 147 Version compiledVersion = null; 148 String requires_version = cr.readUTF8(off, buf); 149 off += 2; 150 if (requires_version != null) { 151 compiledVersion = Version.parse(requires_version); 152 } 153 154 if (compiledVersion == null) { 155 builder.requires(mods, dn); 156 } else { 157 builder.requires(mods, dn, compiledVersion); 158 } 159 } 160 161 // exports_count and exports[exports_count] 162 int exports_count = cr.readUnsignedShort(off); 163 off += 2; 164 if (exports_count > 0) { 165 for (int i=0; i<exports_count; i++) { 166 // CONSTANT_Package_info 167 String pkg = cr.readPackage(off, buf).replace('/', '.'); 168 off += 2; 169 170 int exports_flags = cr.readUnsignedShort(off); 171 off += 2; 172 Set<Exports.Modifier> mods; 173 if (exports_flags == 0) { 174 mods = Collections.emptySet(); 175 } else { 176 mods = new HashSet<>(); 177 if ((exports_flags & ACC_SYNTHETIC) != 0) 178 mods.add(Exports.Modifier.SYNTHETIC); 179 if ((exports_flags & ACC_MANDATED) != 0) 180 mods.add(Exports.Modifier.MANDATED); 181 } 182 183 int exports_to_count = cr.readUnsignedShort(off); 184 off += 2; 185 if (exports_to_count > 0) { 186 Set<String> targets = new HashSet<>(); 187 for (int j=0; j<exports_to_count; j++) { 188 String t = cr.readModule(off, buf); 189 off += 2; 190 targets.add(t); 191 } 192 builder.exports(mods, pkg, targets); 193 } else { 194 builder.exports(mods, pkg); 195 } 196 } 197 } 198 199 // opens_count and opens[opens_count] 200 int open_count = cr.readUnsignedShort(off); 201 off += 2; 202 if (open_count > 0) { 203 for (int i=0; i<open_count; i++) { 204 // CONSTANT_Package_info 205 String pkg = cr.readPackage(off, buf).replace('/', '.'); 206 off += 2; 207 208 int opens_flags = cr.readUnsignedShort(off); 209 off += 2; 210 Set<Opens.Modifier> mods; 211 if (opens_flags == 0) { 212 mods = Collections.emptySet(); 213 } else { 214 mods = new HashSet<>(); 215 if ((opens_flags & ACC_SYNTHETIC) != 0) 216 mods.add(Opens.Modifier.SYNTHETIC); 217 if ((opens_flags & ACC_MANDATED) != 0) 218 mods.add(Opens.Modifier.MANDATED); 219 } 220 221 int opens_to_count = cr.readUnsignedShort(off); 222 off += 2; 223 if (opens_to_count > 0) { 224 Set<String> targets = new HashSet<>(); 225 for (int j=0; j<opens_to_count; j++) { 226 String t = cr.readModule(off, buf); 227 off += 2; 228 targets.add(t); 229 } 230 builder.opens(mods, pkg, targets); 231 } else { 232 builder.opens(mods, pkg); 233 } 234 } 235 } 236 237 // uses_count and uses_index[uses_count] 238 int uses_count = cr.readUnsignedShort(off); 239 off += 2; 240 if (uses_count > 0) { 241 for (int i=0; i<uses_count; i++) { 242 String sn = cr.readClass(off, buf).replace('/', '.'); 243 builder.uses(sn); 244 off += 2; 245 } 246 } 247 248 // provides_count and provides[provides_count] 249 int provides_count = cr.readUnsignedShort(off); 250 off += 2; 251 if (provides_count > 0) { 252 for (int i=0; i<provides_count; i++) { 253 String service = cr.readClass(off, buf).replace('/', '.'); 254 off += 2; 255 int with_count = cr.readUnsignedShort(off); 256 off += 2; 257 List<String> providers = new ArrayList<>(); 258 for (int j=0; j<with_count; j++) { 259 String cn = cr.readClass(off, buf).replace('/', '.'); 260 off += 2; 261 providers.add(cn); 262 } 263 builder.provides(service, providers); 264 } 265 } 266 267 return new ModuleAttribute(builder.build()); 268 } 269 270 @Override 271 protected ByteVector write(ClassWriter cw, 272 byte[] code, 273 int len, 274 int maxStack, 275 int maxLocals) 276 { 277 assert descriptor != null; 278 ByteVector attr = new ByteVector(); 279 280 // module_name 281 String mn = descriptor.name(); 282 int module_name_index = cw.newModule(mn); 283 attr.putShort(module_name_index); 284 285 // module_flags 286 int module_flags = 0; 287 if (descriptor.isOpen()) 288 module_flags |= ACC_OPEN; 289 if (descriptor.isSynthetic()) 290 module_flags |= ACC_SYNTHETIC; 291 attr.putShort(module_flags); 292 293 // module_version 294 Version v = descriptor.version().orElse(null); 295 if (v == null) { 296 attr.putShort(0); 297 } else { 298 int module_version_index = cw.newUTF8(v.toString()); 299 attr.putShort(module_version_index); 300 } 301 302 // requires_count 303 attr.putShort(descriptor.requires().size()); 304 305 // requires[requires_count] 306 for (Requires r : descriptor.requires()) { 307 int requires_index = cw.newModule(r.name()); 308 attr.putShort(requires_index); 309 310 int requires_flags = 0; 311 if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) 312 requires_flags |= ACC_TRANSITIVE; 313 if (r.modifiers().contains(Requires.Modifier.STATIC)) 314 requires_flags |= ACC_STATIC_PHASE; 315 if (r.modifiers().contains(Requires.Modifier.SYNTHETIC)) 316 requires_flags |= ACC_SYNTHETIC; 317 if (r.modifiers().contains(Requires.Modifier.MANDATED)) 318 requires_flags |= ACC_MANDATED; 319 attr.putShort(requires_flags); 320 321 int requires_version_index; 322 v = r.compiledVersion().orElse(null); 323 if (v == null) { 324 requires_version_index = 0; 325 } else { 326 requires_version_index = cw.newUTF8(v.toString()); 327 } 328 attr.putShort(requires_version_index); 329 } 330 331 // exports_count and exports[exports_count]; 332 attr.putShort(descriptor.exports().size()); 333 for (Exports e : descriptor.exports()) { 334 String pkg = e.source().replace('.', '/'); 335 attr.putShort(cw.newPackage(pkg)); 336 337 int exports_flags = 0; 338 if (e.modifiers().contains(Exports.Modifier.SYNTHETIC)) 339 exports_flags |= ACC_SYNTHETIC; 340 if (e.modifiers().contains(Exports.Modifier.MANDATED)) 341 exports_flags |= ACC_MANDATED; 342 attr.putShort(exports_flags); 343 344 if (e.isQualified()) { 345 Set<String> ts = e.targets(); 346 attr.putShort(ts.size()); 347 ts.forEach(target -> attr.putShort(cw.newModule(target))); 348 } else { 349 attr.putShort(0); 350 } 351 } 352 353 // opens_counts and opens[opens_counts] 354 attr.putShort(descriptor.opens().size()); 355 for (Opens obj : descriptor.opens()) { 356 String pkg = obj.source().replace('.', '/'); 357 attr.putShort(cw.newPackage(pkg)); 358 359 int opens_flags = 0; 360 if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC)) 361 opens_flags |= ACC_SYNTHETIC; 362 if (obj.modifiers().contains(Opens.Modifier.MANDATED)) 363 opens_flags |= ACC_MANDATED; 364 attr.putShort(opens_flags); 365 366 if (obj.isQualified()) { 367 Set<String> ts = obj.targets(); 368 attr.putShort(ts.size()); 369 ts.forEach(target -> attr.putShort(cw.newModule(target))); 370 } else { 371 attr.putShort(0); 372 } 373 } 374 375 // uses_count and uses_index[uses_count] 376 if (descriptor.uses().isEmpty()) { 377 attr.putShort(0); 378 } else { 379 attr.putShort(descriptor.uses().size()); 380 for (String s : descriptor.uses()) { 381 String service = s.replace('.', '/'); 382 int index = cw.newClass(service); 383 attr.putShort(index); 384 } 385 } 386 387 // provides_count and provides[provides_count] 388 if (descriptor.provides().isEmpty()) { 389 attr.putShort(0); 390 } else { 391 attr.putShort(descriptor.provides().size()); 392 for (Provides p : descriptor.provides()) { 393 String service = p.service().replace('.', '/'); 394 attr.putShort(cw.newClass(service)); 395 int with_count = p.providers().size(); 396 attr.putShort(with_count); 397 for (String provider : p.providers()) { 398 attr.putShort(cw.newClass(provider.replace('.', '/'))); 399 } 400 } 401 } 402 403 return attr; 404 } 405 } 406 407 /** 408 * ModulePackages attribute. 409 * 410 * <pre> {@code 411 * 412 * ModulePackages_attribute { 413 * // index to CONSTANT_utf8_info structure in constant pool representing 414 * // the string "ModulePackages" 415 * u2 attribute_name_index; 416 * u4 attribute_length; 417 * 418 * // the number of entries in the packages table 419 * u2 packages_count; 420 * { // index to CONSTANT_Package_info structure with the package name 421 * u2 package_index 422 * } packages[package_count]; 423 * 424 * }</pre> 425 */ 426 public static class ModulePackagesAttribute extends Attribute { 427 private final Set<String> packages; 428 429 public ModulePackagesAttribute(Set<String> packages) { 430 super(MODULE_PACKAGES); 431 this.packages = packages; 432 } 433 434 public ModulePackagesAttribute() { 435 this(null); 436 } 437 438 @Override 439 protected Attribute read(ClassReader cr, 440 int off, 441 int len, 442 char[] buf, 443 int codeOff, 444 Label[] labels) 445 { 446 // package count 447 int package_count = cr.readUnsignedShort(off); 448 off += 2; 449 450 // packages 451 Set<String> packages = new HashSet<>(); 452 for (int i=0; i<package_count; i++) { 453 String pkg = cr.readPackage(off, buf).replace('/', '.'); 454 packages.add(pkg); 455 off += 2; 456 } 457 458 return new ModulePackagesAttribute(packages); 459 } 460 461 @Override 462 protected ByteVector write(ClassWriter cw, 463 byte[] code, 464 int len, 465 int maxStack, 466 int maxLocals) 467 { 468 assert packages != null; 469 470 ByteVector attr = new ByteVector(); 471 472 // package_count 473 attr.putShort(packages.size()); 474 475 // packages 476 packages.stream() 477 .map(p -> p.replace('.', '/')) 478 .forEach(p -> attr.putShort(cw.newPackage(p))); 479 480 return attr; 481 } 482 483 } 484 485 /** 486 * ModuleMainClass attribute. 487 * 488 * <pre> {@code 489 * 490 * MainClass_attribute { 491 * // index to CONSTANT_utf8_info structure in constant pool representing 492 * // the string "ModuleMainClass" 493 * u2 attribute_name_index; 494 * u4 attribute_length; 495 * 496 * // index to CONSTANT_Class_info structure with the main class name 497 * u2 main_class_index; 498 * } 499 * 500 * } </pre> 501 */ 502 public static class ModuleMainClassAttribute extends Attribute { 503 private final String mainClass; 504 505 public ModuleMainClassAttribute(String mainClass) { 506 super(MODULE_MAIN_CLASS); 507 this.mainClass = mainClass; 508 } 509 510 public ModuleMainClassAttribute() { 511 this(null); 512 } 513 514 @Override 515 protected Attribute read(ClassReader cr, 516 int off, 517 int len, 518 char[] buf, 519 int codeOff, 520 Label[] labels) 521 { 522 String value = cr.readClass(off, buf).replace('/', '.'); 523 return new ModuleMainClassAttribute(value); 524 } 525 526 @Override 527 protected ByteVector write(ClassWriter cw, 528 byte[] code, 529 int len, 530 int maxStack, 531 int maxLocals) 532 { 533 ByteVector attr = new ByteVector(); 534 int index = cw.newClass(mainClass.replace('.', '/')); 535 attr.putShort(index); 536 return attr; 537 } 538 } 539 540 /** 541 * ModuleTarget attribute. 542 * 543 * <pre> {@code 544 * 545 * TargetPlatform_attribute { 546 * // index to CONSTANT_utf8_info structure in constant pool representing 547 * // the string "ModuleTarget" 548 * u2 attribute_name_index; 549 * u4 attribute_length; 550 * 551 * // index to CONSTANT_utf8_info structure with the OS name 552 * u2 os_name_index; 553 * // index to CONSTANT_utf8_info structure with the OS arch 554 * u2 os_arch_index 555 * // index to CONSTANT_utf8_info structure with the OS version 556 * u2 os_version_index; 557 * } 558 * 559 * } </pre> 560 */ 561 public static class ModuleTargetAttribute extends Attribute { 562 private final String osName; 563 private final String osArch; 564 private final String osVersion; 565 566 public ModuleTargetAttribute(String osName, String osArch, String osVersion) { 567 super(MODULE_TARGET); 568 this.osName = osName; 569 this.osArch = osArch; 570 this.osVersion = osVersion; 571 } 572 573 public ModuleTargetAttribute() { 574 this(null, null, null); 575 } 576 577 @Override 578 protected Attribute read(ClassReader cr, 579 int off, 580 int len, 581 char[] buf, 582 int codeOff, 583 Label[] labels) 584 { 585 586 String osName = null; 587 String osArch = null; 588 String osVersion = null; 589 590 int name_index = cr.readUnsignedShort(off); 591 if (name_index != 0) 592 osName = cr.readUTF8(off, buf); 593 off += 2; 594 595 int arch_index = cr.readUnsignedShort(off); 596 if (arch_index != 0) 597 osArch = cr.readUTF8(off, buf); 598 off += 2; 599 600 int version_index = cr.readUnsignedShort(off); 601 if (version_index != 0) 602 osVersion = cr.readUTF8(off, buf); 603 off += 2; 604 605 return new ModuleTargetAttribute(osName, osArch, osVersion); 606 } 607 608 @Override 609 protected ByteVector write(ClassWriter cw, 610 byte[] code, 611 int len, 612 int maxStack, 613 int maxLocals) 614 { 615 ByteVector attr = new ByteVector(); 616 617 int name_index = 0; 618 if (osName != null && osName.length() > 0) 619 name_index = cw.newUTF8(osName); 620 attr.putShort(name_index); 621 622 int arch_index = 0; 623 if (osArch != null && osArch.length() > 0) 624 arch_index = cw.newUTF8(osArch); 625 attr.putShort(arch_index); 626 627 int version_index = 0; 628 if (osVersion != null && osVersion.length() > 0) 629 version_index = cw.newUTF8(osVersion); 630 attr.putShort(version_index); 631 632 return attr; 633 } 634 } 635 636 /** 637 * ModuleHashes attribute. 638 * 639 * <pre> {@code 640 * 641 * ModuleHashes_attribute { 642 * // index to CONSTANT_utf8_info structure in constant pool representing 643 * // the string "ModuleHashes" 644 * u2 attribute_name_index; 645 * u4 attribute_length; 646 * 647 * // index to CONSTANT_utf8_info structure with algorithm name 648 * u2 algorithm_index; 649 * 650 * // the number of entries in the hashes table 651 * u2 hashes_count; 652 * { u2 module_name_index (index to CONSTANT_Module_info structure) 653 * u2 hash_length; 654 * u1 hash[hash_length]; 655 * } hashes[hashes_count]; 656 * 657 * } </pre> 658 */ 659 static class ModuleHashesAttribute extends Attribute { 660 private final ModuleHashes hashes; 661 662 ModuleHashesAttribute(ModuleHashes hashes) { 663 super(MODULE_HASHES); 664 this.hashes = hashes; 665 } 666 667 ModuleHashesAttribute() { 668 this(null); 669 } 670 671 @Override 672 protected Attribute read(ClassReader cr, 673 int off, 674 int len, 675 char[] buf, 676 int codeOff, 677 Label[] labels) 678 { 679 String algorithm = cr.readUTF8(off, buf); 680 off += 2; 681 682 int hashes_count = cr.readUnsignedShort(off); 683 off += 2; 684 685 Map<String, byte[]> map = new HashMap<>(); 686 for (int i=0; i<hashes_count; i++) { 687 String mn = cr.readModule(off, buf); 688 off += 2; 689 690 int hash_length = cr.readUnsignedShort(off); 691 off += 2; 692 byte[] hash = new byte[hash_length]; 693 for (int j=0; j<hash_length; j++) { 694 hash[j] = (byte) (0xff & cr.readByte(off+j)); 695 } 696 off += hash_length; 697 698 map.put(mn, hash); 699 } 700 701 ModuleHashes hashes = new ModuleHashes(algorithm, map); 702 703 return new ModuleHashesAttribute(hashes); 704 } 705 706 @Override 707 protected ByteVector write(ClassWriter cw, 708 byte[] code, 709 int len, 710 int maxStack, 711 int maxLocals) 712 { 713 ByteVector attr = new ByteVector(); 714 715 int index = cw.newUTF8(hashes.algorithm()); 716 attr.putShort(index); 717 718 Set<String> names = hashes.names(); 719 attr.putShort(names.size()); 720 721 for (String mn : names) { 722 byte[] hash = hashes.hashFor(mn); 723 assert hash != null; 724 attr.putShort(cw.newModule(mn)); 725 726 attr.putShort(hash.length); 727 for (byte b: hash) { 728 attr.putByte(b); 729 } 730 } 731 732 return attr; 733 } 734 } 735 736 /** 737 * ModuleResolution_attribute { 738 * u2 attribute_name_index; // "ModuleResolution" 739 * u4 attribute_length; // 2 740 * u2 resolution_flags; 741 * 742 * The value of the resolution_flags item is a mask of flags used to denote 743 * properties of module resolution. The flags are as follows: 744 * 745 * // Optional 746 * 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT) 747 * 748 * // At most one of: 749 * 0x0002 (WARN_DEPRECATED) 750 * 0x0004 (WARN_DEPRECATED_FOR_REMOVAL) 751 * 0x0008 (WARN_INCUBATING) 752 */ 753 static class ModuleResolutionAttribute extends Attribute { 754 private final int value; 755 756 ModuleResolutionAttribute() { 757 super(MODULE_RESOLUTION); 758 value = 0; 759 } 760 761 ModuleResolutionAttribute(int value) { 762 super(MODULE_RESOLUTION); 763 this.value = value; 764 } 765 766 @Override 767 protected Attribute read(ClassReader cr, 768 int off, 769 int len, 770 char[] buf, 771 int codeOff, 772 Label[] labels) 773 { 774 int flags = cr.readUnsignedShort(off); 775 return new ModuleResolutionAttribute(flags); 776 } 777 778 @Override 779 protected ByteVector write(ClassWriter cw, 780 byte[] code, 781 int len, 782 int maxStack, 783 int maxLocals) 784 { 785 ByteVector attr = new ByteVector(); 786 attr.putShort(value); 787 return attr; 788 } 789 } 790 }