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