1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.classfile.io; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.*; 25import proguard.classfile.attribute.annotation.*; 26import proguard.classfile.attribute.annotation.target.*; 27import proguard.classfile.attribute.annotation.target.visitor.*; 28import proguard.classfile.attribute.annotation.visitor.*; 29import proguard.classfile.attribute.preverification.*; 30import proguard.classfile.attribute.preverification.visitor.*; 31import proguard.classfile.attribute.visitor.*; 32import proguard.classfile.constant.*; 33import proguard.classfile.constant.visitor.ConstantVisitor; 34import proguard.classfile.util.*; 35import proguard.classfile.visitor.*; 36 37import java.io.*; 38 39/** 40 * This ClassVisitor writes out the ProgramClass objects that it visits to the 41 * given DataOutput object. 42 * 43 * @author Eric Lafortune 44 */ 45public class ProgramClassWriter 46extends SimplifiedVisitor 47implements ClassVisitor, 48 MemberVisitor, 49 ConstantVisitor, 50 AttributeVisitor 51{ 52 private RuntimeDataOutput dataOutput; 53 54 private final ConstantBodyWriter constantBodyWriter = new ConstantBodyWriter(); 55 private final AttributeBodyWriter attributeBodyWriter = new AttributeBodyWriter(); 56 private final StackMapFrameBodyWriter stackMapFrameBodyWriter = new StackMapFrameBodyWriter(); 57 private final VerificationTypeBodyWriter verificationTypeBodyWriter = new VerificationTypeBodyWriter(); 58 private final ElementValueBodyWriter elementValueBodyWriter = new ElementValueBodyWriter(); 59 60 61 /** 62 * Creates a new ProgramClassWriter for writing to the given DataOutput. 63 */ 64 public ProgramClassWriter(DataOutput dataOutput) 65 { 66 this.dataOutput = new RuntimeDataOutput(dataOutput); 67 } 68 69 70 // Implementations for ClassVisitor. 71 72 public void visitProgramClass(ProgramClass programClass) 73 { 74 // Write the magic number. 75 dataOutput.writeInt(programClass.u4magic); 76 77 // Write the version numbers. 78 dataOutput.writeShort(ClassUtil.internalMinorClassVersion(programClass.u4version)); 79 dataOutput.writeShort(ClassUtil.internalMajorClassVersion(programClass.u4version)); 80 81 // Write the constant pool. 82 dataOutput.writeShort(programClass.u2constantPoolCount); 83 84 programClass.constantPoolEntriesAccept(this); 85 86 // Write the general class information. 87 dataOutput.writeShort(programClass.u2accessFlags); 88 dataOutput.writeShort(programClass.u2thisClass); 89 dataOutput.writeShort(programClass.u2superClass); 90 91 // Write the interfaces. 92 dataOutput.writeShort(programClass.u2interfacesCount); 93 94 for (int index = 0; index < programClass.u2interfacesCount; index++) 95 { 96 dataOutput.writeShort(programClass.u2interfaces[index]); 97 } 98 99 // Write the fields. 100 dataOutput.writeShort(programClass.u2fieldsCount); 101 102 programClass.fieldsAccept(this); 103 104 // Write the methods. 105 dataOutput.writeShort(programClass.u2methodsCount); 106 107 programClass.methodsAccept(this); 108 109 // Write the class attributes. 110 dataOutput.writeShort(programClass.u2attributesCount); 111 112 programClass.attributesAccept(this); 113 } 114 115 116 public void visitLibraryClass(LibraryClass libraryClass) 117 { 118 } 119 120 121 // Implementations for MemberVisitor. 122 123 public void visitProgramField(ProgramClass programClass, ProgramField programField) 124 { 125 // Write the general field information. 126 dataOutput.writeShort(programField.u2accessFlags); 127 dataOutput.writeShort(programField.u2nameIndex); 128 dataOutput.writeShort(programField.u2descriptorIndex); 129 130 // Write the field attributes. 131 dataOutput.writeShort(programField.u2attributesCount); 132 133 programField.attributesAccept(programClass, this); 134 } 135 136 137 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 138 { 139 // Write the general method information. 140 dataOutput.writeShort(programMethod.u2accessFlags); 141 dataOutput.writeShort(programMethod.u2nameIndex); 142 dataOutput.writeShort(programMethod.u2descriptorIndex); 143 144 // Write the method attributes. 145 dataOutput.writeShort(programMethod.u2attributesCount); 146 147 programMethod.attributesAccept(programClass, this); 148 } 149 150 151 public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) 152 { 153 } 154 155 156 // Implementations for ConstantVisitor. 157 158 public void visitAnyConstant(Clazz clazz, Constant constant) 159 { 160 // Write the tag. 161 dataOutput.writeByte(constant.getTag()); 162 163 // Write the actual body. 164 constant.accept(clazz, constantBodyWriter); 165 } 166 167 168 private class ConstantBodyWriter 169 extends SimplifiedVisitor 170 implements ConstantVisitor 171 { 172 // Implementations for ConstantVisitor. 173 174 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 175 { 176 dataOutput.writeInt(integerConstant.u4value); 177 } 178 179 180 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 181 { 182 dataOutput.writeLong(longConstant.u8value); 183 } 184 185 186 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 187 { 188 dataOutput.writeFloat(floatConstant.f4value); 189 } 190 191 192 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 193 { 194 dataOutput.writeDouble(doubleConstant.f8value); 195 } 196 197 198 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 199 { 200 dataOutput.writeShort(stringConstant.u2stringIndex); 201 } 202 203 204 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 205 { 206 byte[] bytes = utf8Constant.getBytes(); 207 208 dataOutput.writeShort(bytes.length); 209 dataOutput.write(bytes); 210 } 211 212 213 public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) 214 { 215 dataOutput.writeShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex); 216 dataOutput.writeShort(invokeDynamicConstant.u2nameAndTypeIndex); 217 } 218 219 220 public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) 221 { 222 dataOutput.writeByte(methodHandleConstant.u1referenceKind); 223 dataOutput.writeShort(methodHandleConstant.u2referenceIndex); 224 } 225 226 227 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 228 { 229 dataOutput.writeShort(refConstant.u2classIndex); 230 dataOutput.writeShort(refConstant.u2nameAndTypeIndex); 231 } 232 233 234 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 235 { 236 dataOutput.writeShort(classConstant.u2nameIndex); 237 } 238 239 240 public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) 241 { 242 dataOutput.writeShort(methodTypeConstant.u2descriptorIndex); 243 } 244 245 246 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 247 { 248 dataOutput.writeShort(nameAndTypeConstant.u2nameIndex); 249 dataOutput.writeShort(nameAndTypeConstant.u2descriptorIndex); 250 } 251 } 252 253 254 // Implementations for AttributeVisitor. 255 256 public void visitAnyAttribute(Clazz clazz, Attribute attribute) 257 { 258 // Write the attribute name index. 259 dataOutput.writeShort(attribute.u2attributeNameIndex); 260 261 // We'll write the attribute body into an array first, so we can 262 // automatically figure out its length. 263 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 264 265 // Temporarily replace the current data output. 266 RuntimeDataOutput oldDataOutput = dataOutput; 267 dataOutput = new RuntimeDataOutput(new DataOutputStream(byteArrayOutputStream)); 268 269 // Write the attribute body into the array. Note that the 270 // accept method with two dummy null arguments never throws 271 // an UnsupportedOperationException. 272 attribute.accept(clazz, null, null, attributeBodyWriter); 273 274 // Restore the original data output. 275 dataOutput = oldDataOutput; 276 277 // Write the attribute length and body. 278 byte[] info = byteArrayOutputStream.toByteArray(); 279 280 dataOutput.writeInt(info.length); 281 dataOutput.write(info); 282 } 283 284 285 private class AttributeBodyWriter 286 extends SimplifiedVisitor 287 implements AttributeVisitor, 288 BootstrapMethodInfoVisitor, 289 InnerClassesInfoVisitor, 290 ExceptionInfoVisitor, 291 StackMapFrameVisitor, 292 VerificationTypeVisitor, 293 LineNumberInfoVisitor, 294 ParameterInfoVisitor, 295 LocalVariableInfoVisitor, 296 LocalVariableTypeInfoVisitor, 297 AnnotationVisitor, 298 TypeAnnotationVisitor, 299 TargetInfoVisitor, 300 TypePathInfoVisitor, 301 LocalVariableTargetElementVisitor, 302 ElementValueVisitor 303 { 304 // Implementations for AttributeVisitor. 305 306 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 307 { 308 // Write the unknown information. 309 dataOutput.write(unknownAttribute.info); 310 } 311 312 313 public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) 314 { 315 // Write the bootstrap methods. 316 dataOutput.writeShort(bootstrapMethodsAttribute.u2bootstrapMethodsCount); 317 318 bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this); 319 } 320 321 322 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 323 { 324 dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex); 325 } 326 327 328 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 329 { 330 dataOutput.writeShort(sourceDirAttribute.u2sourceDirIndex); 331 } 332 333 334 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 335 { 336 // Write the inner classes. 337 dataOutput.writeShort(innerClassesAttribute.u2classesCount); 338 339 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 340 } 341 342 343 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 344 { 345 dataOutput.writeShort(enclosingMethodAttribute.u2classIndex); 346 dataOutput.writeShort(enclosingMethodAttribute.u2nameAndTypeIndex); 347 } 348 349 350 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 351 { 352 // This attribute does not contain any additional information. 353 } 354 355 356 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 357 { 358 // This attribute does not contain any additional information. 359 } 360 361 362 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 363 { 364 dataOutput.writeShort(signatureAttribute.u2signatureIndex); 365 } 366 367 368 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 369 { 370 dataOutput.writeShort(constantValueAttribute.u2constantValueIndex); 371 } 372 373 374 public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) 375 { 376 // Write the parameter information. 377 dataOutput.writeByte(methodParametersAttribute.u1parametersCount); 378 379 methodParametersAttribute.parametersAccept(clazz, method, this); 380 } 381 382 383 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 384 { 385 // Write the exceptions. 386 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTableLength); 387 388 for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) 389 { 390 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTable[index]); 391 } 392 } 393 394 395 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 396 { 397 // Write the stack size and local variable frame size. 398 dataOutput.writeShort(codeAttribute.u2maxStack); 399 dataOutput.writeShort(codeAttribute.u2maxLocals); 400 401 // Write the byte code. 402 dataOutput.writeInt(codeAttribute.u4codeLength); 403 404 dataOutput.write(codeAttribute.code, 0, codeAttribute.u4codeLength); 405 406 // Write the exceptions. 407 dataOutput.writeShort(codeAttribute.u2exceptionTableLength); 408 409 codeAttribute.exceptionsAccept(clazz, method, this); 410 411 // Write the code attributes. 412 dataOutput.writeShort(codeAttribute.u2attributesCount); 413 414 codeAttribute.attributesAccept(clazz, method, ProgramClassWriter.this); 415 } 416 417 418 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 419 { 420 // Write the stack map frames (only full frames, without tag). 421 dataOutput.writeShort(stackMapAttribute.u2stackMapFramesCount); 422 423 stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, stackMapFrameBodyWriter); 424 } 425 426 427 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 428 { 429 // Write the stack map frames. 430 dataOutput.writeShort(stackMapTableAttribute.u2stackMapFramesCount); 431 432 stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 433 } 434 435 436 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 437 { 438 // Write the line numbers. 439 dataOutput.writeShort(lineNumberTableAttribute.u2lineNumberTableLength); 440 441 lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this); 442 } 443 444 445 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 446 { 447 // Write the local variables. 448 dataOutput.writeShort(localVariableTableAttribute.u2localVariableTableLength); 449 450 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 451 } 452 453 454 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 455 { 456 // Write the local variable types. 457 dataOutput.writeShort(localVariableTypeTableAttribute.u2localVariableTypeTableLength); 458 459 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 460 } 461 462 463 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 464 { 465 // Write the annotations. 466 dataOutput.writeShort(annotationsAttribute.u2annotationsCount); 467 468 annotationsAttribute.annotationsAccept(clazz, this); 469 } 470 471 472 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 473 { 474 // Write the parameter annotations. 475 dataOutput.writeByte(parameterAnnotationsAttribute.u1parametersCount); 476 477 for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++) 478 { 479 // Write the parameter annotations of the given parameter. 480 int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; 481 Annotation[] annotations = parameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; 482 483 dataOutput.writeShort(u2annotationsCount); 484 485 for (int index = 0; index < u2annotationsCount; index++) 486 { 487 visitAnnotation(clazz, annotations[index]); 488 } 489 490 } 491 } 492 493 494 public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) 495 { 496 // Write the type annotations. 497 dataOutput.writeShort(typeAnnotationsAttribute.u2annotationsCount); 498 499 typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); 500 } 501 502 503 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 504 { 505 // Write the default element value. 506 annotationDefaultAttribute.defaultValue.accept(clazz, null, this); 507 } 508 509 510 // Implementations for BootstrapMethodInfoVisitor. 511 512 public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) 513 { 514 dataOutput.writeShort(bootstrapMethodInfo.u2methodHandleIndex); 515 516 // Write the bootstrap method arguments. 517 dataOutput.writeShort(bootstrapMethodInfo.u2methodArgumentCount); 518 519 for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++) 520 { 521 dataOutput.writeShort(bootstrapMethodInfo.u2methodArguments[index]); 522 } 523 } 524 525 526 // Implementations for InnerClassesInfoVisitor. 527 528 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 529 { 530 dataOutput.writeShort(innerClassesInfo.u2innerClassIndex); 531 dataOutput.writeShort(innerClassesInfo.u2outerClassIndex); 532 dataOutput.writeShort(innerClassesInfo.u2innerNameIndex); 533 dataOutput.writeShort(innerClassesInfo.u2innerClassAccessFlags); 534 } 535 536 537 // Implementations for ExceptionInfoVisitor. 538 539 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 540 { 541 dataOutput.writeShort(exceptionInfo.u2startPC); 542 dataOutput.writeShort(exceptionInfo.u2endPC); 543 dataOutput.writeShort(exceptionInfo.u2handlerPC); 544 dataOutput.writeShort(exceptionInfo.u2catchType); 545 } 546 547 548 // Implementations for StackMapFrameVisitor. 549 550 public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) 551 { 552 // Write the stack map frame tag. 553 dataOutput.writeByte(stackMapFrame.getTag()); 554 555 // Write the actual body. 556 stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameBodyWriter); 557 } 558 559 560 // Implementations for LineNumberInfoVisitor. 561 562 public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 563 { 564 dataOutput.writeShort(lineNumberInfo.u2startPC); 565 dataOutput.writeShort(lineNumberInfo.u2lineNumber); 566 } 567 568 569 // Implementations for ParameterInfoVisitor. 570 571 public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) 572 { 573 dataOutput.writeShort(parameterInfo.u2nameIndex); 574 dataOutput.writeShort(parameterInfo.u2accessFlags); 575 } 576 577 578 // Implementations for LocalVariableInfoVisitor. 579 580 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 581 { 582 dataOutput.writeShort(localVariableInfo.u2startPC); 583 dataOutput.writeShort(localVariableInfo.u2length); 584 dataOutput.writeShort(localVariableInfo.u2nameIndex); 585 dataOutput.writeShort(localVariableInfo.u2descriptorIndex); 586 dataOutput.writeShort(localVariableInfo.u2index); 587 } 588 589 590 // Implementations for LocalVariableTypeInfoVisitor. 591 592 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 593 { 594 dataOutput.writeShort(localVariableTypeInfo.u2startPC); 595 dataOutput.writeShort(localVariableTypeInfo.u2length); 596 dataOutput.writeShort(localVariableTypeInfo.u2nameIndex); 597 dataOutput.writeShort(localVariableTypeInfo.u2signatureIndex); 598 dataOutput.writeShort(localVariableTypeInfo.u2index); 599 } 600 601 602 // Implementations for AnnotationVisitor. 603 604 public void visitAnnotation(Clazz clazz, Annotation annotation) 605 { 606 // Write the annotation type. 607 dataOutput.writeShort(annotation.u2typeIndex); 608 609 // Write the element value pairs. 610 dataOutput.writeShort(annotation.u2elementValuesCount); 611 612 annotation.elementValuesAccept(clazz, this); 613 } 614 615 616 // Implementations for TypeAnnotationVisitor. 617 618 public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) 619 { 620 // Write the target info. 621 dataOutput.writeByte(typeAnnotation.targetInfo.u1targetType); 622 623 typeAnnotation.targetInfoAccept(clazz, this); 624 625 // Write the type path. 626 dataOutput.writeByte(typeAnnotation.typePath.length); 627 628 typeAnnotation.typePathInfosAccept(clazz, this); 629 630 // Write the actual annotation. 631 visitAnnotation(clazz, typeAnnotation); 632 } 633 634 635 // Implementations for TargetInfoVisitor. 636 637 public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) 638 { 639 dataOutput.writeByte(typeParameterTargetInfo.u1typeParameterIndex); 640 } 641 642 643 public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) 644 { 645 dataOutput.writeShort(superTypeTargetInfo.u2superTypeIndex); 646 } 647 648 649 public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) 650 { 651 dataOutput.writeByte(typeParameterBoundTargetInfo.u1typeParameterIndex); 652 dataOutput.writeByte(typeParameterBoundTargetInfo.u1boundIndex); 653 } 654 655 656 public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) 657 { 658 } 659 660 661 public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) 662 { 663 dataOutput.writeByte(formalParameterTargetInfo.u1formalParameterIndex); 664 } 665 666 667 public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) 668 { 669 dataOutput.writeShort(throwsTargetInfo.u2throwsTypeIndex); 670 } 671 672 673 public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) 674 { 675 // Write the local variable target elements. 676 dataOutput.writeShort(localVariableTargetInfo.u2tableLength); 677 678 localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); 679 } 680 681 682 public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) 683 { 684 dataOutput.writeShort(catchTargetInfo.u2exceptionTableIndex); 685 } 686 687 688 public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) 689 { 690 dataOutput.writeShort(offsetTargetInfo.u2offset); 691 } 692 693 694 public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) 695 { 696 dataOutput.writeShort(typeArgumentTargetInfo.u2offset); 697 dataOutput.writeByte(typeArgumentTargetInfo.u1typeArgumentIndex); 698 } 699 700 701 // Implementations for TypePathInfoVisitor. 702 703 public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) 704 { 705 dataOutput.writeByte(typePathInfo.u1typePathKind); 706 dataOutput.writeByte(typePathInfo.u1typeArgumentIndex); 707 } 708 709 710 // Implementations for LocalVariableTargetElementVisitor. 711 712 public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) 713 { 714 dataOutput.writeShort(localVariableTargetElement.u2startPC); 715 dataOutput.writeShort(localVariableTargetElement.u2length); 716 dataOutput.writeShort(localVariableTargetElement.u2index); 717 } 718 719 720 // Implementations for ElementValueVisitor. 721 722 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) 723 { 724 // Write the element name index, if applicable. 725 int u2elementNameIndex = elementValue.u2elementNameIndex; 726 if (u2elementNameIndex != 0) 727 { 728 dataOutput.writeShort(u2elementNameIndex); 729 } 730 731 // Write the tag. 732 dataOutput.writeByte(elementValue.getTag()); 733 734 // Write the actual body. 735 elementValue.accept(clazz, annotation, elementValueBodyWriter); 736 } 737 } 738 739 740 private class StackMapFrameBodyWriter 741 extends SimplifiedVisitor 742 implements StackMapFrameVisitor, 743 VerificationTypeVisitor 744 { 745 public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) 746 { 747 if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) 748 { 749 dataOutput.writeShort(sameZeroFrame.u2offsetDelta); 750 } 751 } 752 753 754 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 755 { 756 if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) 757 { 758 dataOutput.writeShort(sameOneFrame.u2offsetDelta); 759 } 760 761 // Write the verification type of the stack entry. 762 sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 763 } 764 765 766 public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) 767 { 768 dataOutput.writeShort(lessZeroFrame.u2offsetDelta); 769 } 770 771 772 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 773 { 774 dataOutput.writeShort(moreZeroFrame.u2offsetDelta); 775 776 // Write the verification types of the additional local variables. 777 moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 778 } 779 780 781 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 782 { 783 dataOutput.writeShort(fullFrame.u2offsetDelta); 784 785 // Write the verification types of the local variables. 786 dataOutput.writeShort(fullFrame.variablesCount); 787 fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 788 789 // Write the verification types of the stack entries. 790 dataOutput.writeShort(fullFrame.stackCount); 791 fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 792 } 793 794 795 // Implementations for VerificationTypeVisitor. 796 797 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 798 { 799 // Write the verification type tag. 800 dataOutput.writeByte(verificationType.getTag()); 801 802 // Write the actual body. 803 verificationType.accept(clazz, method, codeAttribute, offset, verificationTypeBodyWriter); 804 } 805 } 806 807 808 private class VerificationTypeBodyWriter 809 extends SimplifiedVisitor 810 implements VerificationTypeVisitor 811 { 812 // Implementations for VerificationTypeVisitor. 813 814 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 815 { 816 // Most verification types don't contain any additional information. 817 } 818 819 820 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 821 { 822 dataOutput.writeShort(objectType.u2classIndex); 823 } 824 825 826 public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 827 { 828 dataOutput.writeShort(uninitializedType.u2newInstructionOffset); 829 } 830 } 831 832 833 private class ElementValueBodyWriter 834 extends SimplifiedVisitor 835 implements ElementValueVisitor 836 { 837 // Implementations for ElementValueVisitor. 838 839 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 840 { 841 dataOutput.writeShort(constantElementValue.u2constantValueIndex); 842 } 843 844 845 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 846 { 847 dataOutput.writeShort(enumConstantElementValue.u2typeNameIndex); 848 dataOutput.writeShort(enumConstantElementValue.u2constantNameIndex); 849 } 850 851 852 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 853 { 854 dataOutput.writeShort(classElementValue.u2classInfoIndex); 855 } 856 857 858 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 859 { 860 // Write the annotation. 861 attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue); 862 } 863 864 865 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 866 { 867 // Write the element values. 868 dataOutput.writeShort(arrayElementValue.u2elementValuesCount); 869 870 arrayElementValue.elementValuesAccept(clazz, annotation, attributeBodyWriter); 871 } 872 } 873} 874