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 Version v = descriptor.version().orElse(null); 296 if (v == null) { 297 attr.putShort(0); 298 } else { 299 int module_version_index = cw.newUTF8(v.toString()); 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 v = r.compiledVersion().orElse(null); 324 if (v == null) { 325 requires_version_index = 0; 326 } else { 327 requires_version_index = cw.newUTF8(v.toString()); 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 * // index to CONSTANT_utf8_info structure with the OS version 557 * u2 os_version_index; 558 * } 559 * 560 * } </pre> 561 */ 562 public static class ModuleTargetAttribute extends Attribute { 563 private final String osName; 564 private final String osArch; 565 private final String osVersion; 566 567 public ModuleTargetAttribute(String osName, String osArch, String osVersion) { 568 super(MODULE_TARGET); 569 this.osName = osName; 570 this.osArch = osArch; 571 this.osVersion = osVersion; 572 } 573 574 public ModuleTargetAttribute() { 575 this(null, null, null); 576 } 577 578 @Override 579 protected Attribute read(ClassReader cr, 580 int off, 581 int len, 582 char[] buf, 583 int codeOff, 584 Label[] labels) 585 { 586 587 String osName = null; 588 String osArch = null; 589 String osVersion = null; 590 591 int name_index = cr.readUnsignedShort(off); 592 if (name_index != 0) 593 osName = cr.readUTF8(off, buf); 594 off += 2; 595 596 int arch_index = cr.readUnsignedShort(off); 597 if (arch_index != 0) 598 osArch = cr.readUTF8(off, buf); 599 off += 2; 600 601 int version_index = cr.readUnsignedShort(off); 602 if (version_index != 0) 603 osVersion = cr.readUTF8(off, buf); 604 off += 2; 605 606 return new ModuleTargetAttribute(osName, osArch, osVersion); 607 } 608 609 @Override 610 protected ByteVector write(ClassWriter cw, 611 byte[] code, 612 int len, 613 int maxStack, 614 int maxLocals) 615 { 616 ByteVector attr = new ByteVector(); 617 618 int name_index = 0; 619 if (osName != null && osName.length() > 0) 620 name_index = cw.newUTF8(osName); 621 attr.putShort(name_index); 622 623 int arch_index = 0; 624 if (osArch != null && osArch.length() > 0) 625 arch_index = cw.newUTF8(osArch); 626 attr.putShort(arch_index); 627 628 int version_index = 0; 629 if (osVersion != null && osVersion.length() > 0) 630 version_index = cw.newUTF8(osVersion); 631 attr.putShort(version_index); 632 633 return attr; 634 } 635 } 636 637 /** 638 * ModuleHashes attribute. 639 * 640 * <pre> {@code 641 * 642 * ModuleHashes_attribute { 643 * // index to CONSTANT_utf8_info structure in constant pool representing 644 * // the string "ModuleHashes" 645 * u2 attribute_name_index; 646 * u4 attribute_length; 647 * 648 * // index to CONSTANT_utf8_info structure with algorithm name 649 * u2 algorithm_index; 650 * 651 * // the number of entries in the hashes table 652 * u2 hashes_count; 653 * { u2 module_name_index (index to CONSTANT_Module_info structure) 654 * u2 hash_length; 655 * u1 hash[hash_length]; 656 * } hashes[hashes_count]; 657 * 658 * } </pre> 659 */ 660 static class ModuleHashesAttribute extends Attribute { 661 private final ModuleHashes hashes; 662 663 ModuleHashesAttribute(ModuleHashes hashes) { 664 super(MODULE_HASHES); 665 this.hashes = hashes; 666 } 667 668 ModuleHashesAttribute() { 669 this(null); 670 } 671 672 @Override 673 protected Attribute read(ClassReader cr, 674 int off, 675 int len, 676 char[] buf, 677 int codeOff, 678 Label[] labels) 679 { 680 String algorithm = cr.readUTF8(off, buf); 681 off += 2; 682 683 int hashes_count = cr.readUnsignedShort(off); 684 off += 2; 685 686 Map<String, byte[]> map = new HashMap<>(); 687 for (int i=0; i<hashes_count; i++) { 688 String mn = cr.readModule(off, buf); 689 off += 2; 690 691 int hash_length = cr.readUnsignedShort(off); 692 off += 2; 693 byte[] hash = new byte[hash_length]; 694 for (int j=0; j<hash_length; j++) { 695 hash[j] = (byte) (0xff & cr.readByte(off+j)); 696 } 697 off += hash_length; 698 699 map.put(mn, hash); 700 } 701 702 ModuleHashes hashes = new ModuleHashes(algorithm, map); 703 704 return new ModuleHashesAttribute(hashes); 705 } 706 707 @Override 708 protected ByteVector write(ClassWriter cw, 709 byte[] code, 710 int len, 711 int maxStack, 712 int maxLocals) 713 { 714 ByteVector attr = new ByteVector(); 715 716 int index = cw.newUTF8(hashes.algorithm()); 717 attr.putShort(index); 718 719 Set<String> names = hashes.names(); 720 attr.putShort(names.size()); 721 722 for (String mn : names) { 723 byte[] hash = hashes.hashFor(mn); 724 assert hash != null; 725 attr.putShort(cw.newModule(mn)); 726 727 attr.putShort(hash.length); 728 for (byte b: hash) { 729 attr.putByte(b); 730 } 731 } 732 733 return attr; 734 } 735 } 736 737 /** 738 * ModuleResolution_attribute { 739 * u2 attribute_name_index; // "ModuleResolution" 740 * u4 attribute_length; // 2 741 * u2 resolution_flags; 742 * 743 * The value of the resolution_flags item is a mask of flags used to denote 744 * properties of module resolution. The flags are as follows: 745 * 746 * // Optional 747 * 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT) 748 * 749 * // At most one of: 750 * 0x0002 (WARN_DEPRECATED) 751 * 0x0004 (WARN_DEPRECATED_FOR_REMOVAL) 752 * 0x0008 (WARN_INCUBATING) 753 */ 754 static class ModuleResolutionAttribute extends Attribute { 755 private final int value; 756 757 ModuleResolutionAttribute() { 758 super(MODULE_RESOLUTION); 759 value = 0; 760 } 761 762 ModuleResolutionAttribute(int value) { 763 super(MODULE_RESOLUTION); 764 this.value = value; 765 } 766 767 @Override 768 protected Attribute read(ClassReader cr, 769 int off, 770 int len, 771 char[] buf, 772 int codeOff, 773 Label[] labels) 774 { 775 int flags = cr.readUnsignedShort(off); 776 return new ModuleResolutionAttribute(flags); 777 } 778 779 @Override 780 protected ByteVector write(ClassWriter cw, 781 byte[] code, 782 int len, 783 int maxStack, 784 int maxLocals) 785 { 786 ByteVector attr = new ByteVector(); 787 attr.putShort(value); 788 return attr; 789 } 790 } 791 }