1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2013 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.visitor.*; 27import proguard.classfile.attribute.preverification.*; 28import proguard.classfile.attribute.preverification.visitor.*; 29import proguard.classfile.attribute.visitor.*; 30import proguard.classfile.constant.*; 31import proguard.classfile.constant.visitor.ConstantVisitor; 32import proguard.classfile.util.*; 33import proguard.classfile.visitor.*; 34 35import java.io.*; 36 37/** 38 * This ClassVisitor writes out the ProgramClass objects that it visits to the 39 * given DataOutput object. 40 * 41 * @author Eric Lafortune 42 */ 43public class ProgramClassWriter 44extends SimplifiedVisitor 45implements ClassVisitor, 46 MemberVisitor, 47 ConstantVisitor, 48 AttributeVisitor 49{ 50 private RuntimeDataOutput dataOutput; 51 52 private final ConstantBodyWriter constantBodyWriter = new ConstantBodyWriter(); 53 private final AttributeBodyWriter attributeBodyWriter = new AttributeBodyWriter(); 54 private final StackMapFrameBodyWriter stackMapFrameBodyWriter = new StackMapFrameBodyWriter(); 55 private final VerificationTypeBodyWriter verificationTypeBodyWriter = new VerificationTypeBodyWriter(); 56 private final ElementValueBodyWriter elementValueBodyWriter = new ElementValueBodyWriter(); 57 58 59 /** 60 * Creates a new ProgramClassWriter for writing to the given DataOutput. 61 */ 62 public ProgramClassWriter(DataOutput dataOutput) 63 { 64 this.dataOutput = new RuntimeDataOutput(dataOutput); 65 } 66 67 68 // Implementations for ClassVisitor. 69 70 public void visitProgramClass(ProgramClass programClass) 71 { 72 // Write the magic number. 73 dataOutput.writeInt(programClass.u4magic); 74 75 // Write the version numbers. 76 dataOutput.writeShort(ClassUtil.internalMinorClassVersion(programClass.u4version)); 77 dataOutput.writeShort(ClassUtil.internalMajorClassVersion(programClass.u4version)); 78 79 // Write the constant pool. 80 dataOutput.writeShort(programClass.u2constantPoolCount); 81 82 programClass.constantPoolEntriesAccept(this); 83 84 // Write the general class information. 85 dataOutput.writeShort(programClass.u2accessFlags); 86 dataOutput.writeShort(programClass.u2thisClass); 87 dataOutput.writeShort(programClass.u2superClass); 88 89 // Write the interfaces. 90 dataOutput.writeShort(programClass.u2interfacesCount); 91 92 for (int index = 0; index < programClass.u2interfacesCount; index++) 93 { 94 dataOutput.writeShort(programClass.u2interfaces[index]); 95 } 96 97 // Write the fields. 98 dataOutput.writeShort(programClass.u2fieldsCount); 99 100 programClass.fieldsAccept(this); 101 102 // Write the methods. 103 dataOutput.writeShort(programClass.u2methodsCount); 104 105 programClass.methodsAccept(this); 106 107 // Write the class attributes. 108 dataOutput.writeShort(programClass.u2attributesCount); 109 110 programClass.attributesAccept(this); 111 } 112 113 114 public void visitLibraryClass(LibraryClass libraryClass) 115 { 116 } 117 118 119 // Implementations for MemberVisitor. 120 121 public void visitProgramField(ProgramClass programClass, ProgramField programField) 122 { 123 // Write the general field information. 124 dataOutput.writeShort(programField.u2accessFlags); 125 dataOutput.writeShort(programField.u2nameIndex); 126 dataOutput.writeShort(programField.u2descriptorIndex); 127 128 // Write the field attributes. 129 dataOutput.writeShort(programField.u2attributesCount); 130 131 programField.attributesAccept(programClass, this); 132 } 133 134 135 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 136 { 137 // Write the general method information. 138 dataOutput.writeShort(programMethod.u2accessFlags); 139 dataOutput.writeShort(programMethod.u2nameIndex); 140 dataOutput.writeShort(programMethod.u2descriptorIndex); 141 142 // Write the method attributes. 143 dataOutput.writeShort(programMethod.u2attributesCount); 144 145 programMethod.attributesAccept(programClass, this); 146 } 147 148 149 public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) 150 { 151 } 152 153 154 // Implementations for ConstantVisitor. 155 156 public void visitAnyConstant(Clazz clazz, Constant constant) 157 { 158 // Write the tag. 159 dataOutput.writeByte(constant.getTag()); 160 161 // Write the actual body. 162 constant.accept(clazz, constantBodyWriter); 163 } 164 165 166 private class ConstantBodyWriter 167 extends SimplifiedVisitor 168 implements ConstantVisitor 169 { 170 // Implementations for ConstantVisitor. 171 172 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 173 { 174 dataOutput.writeInt(integerConstant.u4value); 175 } 176 177 178 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 179 { 180 dataOutput.writeLong(longConstant.u8value); 181 } 182 183 184 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 185 { 186 dataOutput.writeFloat(floatConstant.f4value); 187 } 188 189 190 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 191 { 192 dataOutput.writeDouble(doubleConstant.f8value); 193 } 194 195 196 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 197 { 198 dataOutput.writeShort(stringConstant.u2stringIndex); 199 } 200 201 202 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 203 { 204 byte[] bytes = utf8Constant.getBytes(); 205 206 dataOutput.writeShort(bytes.length); 207 dataOutput.write(bytes); 208 } 209 210 211 public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) 212 { 213 dataOutput.writeShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex); 214 dataOutput.writeShort(invokeDynamicConstant.u2nameAndTypeIndex); 215 } 216 217 218 public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) 219 { 220 dataOutput.writeByte(methodHandleConstant.u1referenceKind); 221 dataOutput.writeShort(methodHandleConstant.u2referenceIndex); 222 } 223 224 225 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 226 { 227 dataOutput.writeShort(refConstant.u2classIndex); 228 dataOutput.writeShort(refConstant.u2nameAndTypeIndex); 229 } 230 231 232 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 233 { 234 dataOutput.writeShort(classConstant.u2nameIndex); 235 } 236 237 238 public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) 239 { 240 dataOutput.writeShort(methodTypeConstant.u2descriptorIndex); 241 } 242 243 244 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 245 { 246 dataOutput.writeShort(nameAndTypeConstant.u2nameIndex); 247 dataOutput.writeShort(nameAndTypeConstant.u2descriptorIndex); 248 } 249 } 250 251 252 // Implementations for AttributeVisitor. 253 254 public void visitAnyAttribute(Clazz clazz, Attribute attribute) 255 { 256 // Write the attribute name index. 257 dataOutput.writeShort(attribute.u2attributeNameIndex); 258 259 // We'll write the attribute body into an array first, so we can 260 // automatically figure out its length. 261 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 262 263 // Temporarily replace the current data output. 264 RuntimeDataOutput oldDataOutput = dataOutput; 265 dataOutput = new RuntimeDataOutput(new DataOutputStream(byteArrayOutputStream)); 266 267 // Write the attribute body into the array. Note that the 268 // accept method with two dummy null arguments never throws 269 // an UnsupportedOperationException. 270 attribute.accept(clazz, null, null, attributeBodyWriter); 271 272 // Restore the original data output. 273 dataOutput = oldDataOutput; 274 275 // Write the attribute length and body. 276 byte[] info = byteArrayOutputStream.toByteArray(); 277 278 dataOutput.writeInt(info.length); 279 dataOutput.write(info); 280 } 281 282 283 private class AttributeBodyWriter 284 extends SimplifiedVisitor 285 implements AttributeVisitor, 286 BootstrapMethodInfoVisitor, 287 InnerClassesInfoVisitor, 288 ExceptionInfoVisitor, 289 StackMapFrameVisitor, 290 VerificationTypeVisitor, 291 LineNumberInfoVisitor, 292 LocalVariableInfoVisitor, 293 LocalVariableTypeInfoVisitor, 294 AnnotationVisitor, 295 ElementValueVisitor 296 { 297 // Implementations for AttributeVisitor. 298 299 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 300 { 301 // Write the unknown information. 302 dataOutput.write(unknownAttribute.info); 303 } 304 305 306 public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) 307 { 308 // Write the bootstrap methods. 309 dataOutput.writeShort(bootstrapMethodsAttribute.u2bootstrapMethodsCount); 310 311 bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this); 312 } 313 314 315 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 316 { 317 dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex); 318 } 319 320 321 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 322 { 323 dataOutput.writeShort(sourceDirAttribute.u2sourceDirIndex); 324 } 325 326 327 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 328 { 329 // Write the inner classes. 330 dataOutput.writeShort(innerClassesAttribute.u2classesCount); 331 332 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 333 } 334 335 336 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 337 { 338 dataOutput.writeShort(enclosingMethodAttribute.u2classIndex); 339 dataOutput.writeShort(enclosingMethodAttribute.u2nameAndTypeIndex); 340 } 341 342 343 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 344 { 345 // This attribute does not contain any additional information. 346 } 347 348 349 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 350 { 351 // This attribute does not contain any additional information. 352 } 353 354 355 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 356 { 357 dataOutput.writeShort(signatureAttribute.u2signatureIndex); 358 } 359 360 361 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 362 { 363 dataOutput.writeShort(constantValueAttribute.u2constantValueIndex); 364 } 365 366 367 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 368 { 369 // Write the exceptions. 370 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTableLength); 371 372 for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) 373 { 374 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTable[index]); 375 } 376 } 377 378 379 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 380 { 381 // Write the stack size and local variable frame size. 382 dataOutput.writeShort(codeAttribute.u2maxStack); 383 dataOutput.writeShort(codeAttribute.u2maxLocals); 384 385 // Write the byte code. 386 dataOutput.writeInt(codeAttribute.u4codeLength); 387 388 dataOutput.write(codeAttribute.code, 0, codeAttribute.u4codeLength); 389 390 // Write the exceptions. 391 dataOutput.writeShort(codeAttribute.u2exceptionTableLength); 392 393 codeAttribute.exceptionsAccept(clazz, method, this); 394 395 // Write the code attributes. 396 dataOutput.writeShort(codeAttribute.u2attributesCount); 397 398 codeAttribute.attributesAccept(clazz, method, ProgramClassWriter.this); 399 } 400 401 402 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 403 { 404 // Write the stack map frames (only full frames, without tag). 405 dataOutput.writeShort(stackMapAttribute.u2stackMapFramesCount); 406 407 stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, stackMapFrameBodyWriter); 408 } 409 410 411 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 412 { 413 // Write the stack map frames. 414 dataOutput.writeShort(stackMapTableAttribute.u2stackMapFramesCount); 415 416 stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 417 } 418 419 420 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 421 { 422 // Write the line numbers. 423 dataOutput.writeShort(lineNumberTableAttribute.u2lineNumberTableLength); 424 425 lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this); 426 } 427 428 429 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 430 { 431 // Write the local variables. 432 dataOutput.writeShort(localVariableTableAttribute.u2localVariableTableLength); 433 434 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 435 } 436 437 438 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 439 { 440 // Write the local variable types. 441 dataOutput.writeShort(localVariableTypeTableAttribute.u2localVariableTypeTableLength); 442 443 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 444 } 445 446 447 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 448 { 449 // Write the annotations. 450 dataOutput.writeShort(annotationsAttribute.u2annotationsCount); 451 452 annotationsAttribute.annotationsAccept(clazz, this); 453 } 454 455 456 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 457 { 458 // Write the parameter annotations. 459 dataOutput.writeByte(parameterAnnotationsAttribute.u2parametersCount); 460 461 for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) 462 { 463 // Write the parameter annotations of the given parameter. 464 int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; 465 Annotation[] annotations = parameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; 466 467 dataOutput.writeShort(u2annotationsCount); 468 469 for (int index = 0; index < u2annotationsCount; index++) 470 { 471 visitAnnotation(clazz, annotations[index]); 472 } 473 474 } 475 } 476 477 478 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 479 { 480 // Write the default element value. 481 annotationDefaultAttribute.defaultValue.accept(clazz, null, this); 482 } 483 484 485 // Implementations for BootstrapMethodInfoVisitor. 486 487 public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) 488 { 489 dataOutput.writeShort(bootstrapMethodInfo.u2methodHandleIndex); 490 491 // Write the bootstrap method arguments. 492 dataOutput.writeShort(bootstrapMethodInfo.u2methodArgumentCount); 493 494 for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++) 495 { 496 dataOutput.writeShort(bootstrapMethodInfo.u2methodArguments[index]); 497 } 498 } 499 500 501 // Implementations for InnerClassesInfoVisitor. 502 503 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 504 { 505 dataOutput.writeShort(innerClassesInfo.u2innerClassIndex); 506 dataOutput.writeShort(innerClassesInfo.u2outerClassIndex); 507 dataOutput.writeShort(innerClassesInfo.u2innerNameIndex); 508 dataOutput.writeShort(innerClassesInfo.u2innerClassAccessFlags); 509 } 510 511 512 // Implementations for ExceptionInfoVisitor. 513 514 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 515 { 516 dataOutput.writeShort(exceptionInfo.u2startPC); 517 dataOutput.writeShort(exceptionInfo.u2endPC); 518 dataOutput.writeShort(exceptionInfo.u2handlerPC); 519 dataOutput.writeShort(exceptionInfo.u2catchType); 520 } 521 522 523 // Implementations for StackMapFrameVisitor. 524 525 public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) 526 { 527 // Write the stack map frame tag. 528 dataOutput.writeByte(stackMapFrame.getTag()); 529 530 // Write the actual body. 531 stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameBodyWriter); 532 } 533 534 535 // Implementations for LineNumberInfoVisitor. 536 537 public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 538 { 539 dataOutput.writeShort(lineNumberInfo.u2startPC); 540 dataOutput.writeShort(lineNumberInfo.u2lineNumber); 541 } 542 543 544 // Implementations for LocalVariableInfoVisitor. 545 546 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 547 { 548 dataOutput.writeShort(localVariableInfo.u2startPC); 549 dataOutput.writeShort(localVariableInfo.u2length); 550 dataOutput.writeShort(localVariableInfo.u2nameIndex); 551 dataOutput.writeShort(localVariableInfo.u2descriptorIndex); 552 dataOutput.writeShort(localVariableInfo.u2index); 553 } 554 555 556 // Implementations for LocalVariableTypeInfoVisitor. 557 558 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 559 { 560 dataOutput.writeShort(localVariableTypeInfo.u2startPC); 561 dataOutput.writeShort(localVariableTypeInfo.u2length); 562 dataOutput.writeShort(localVariableTypeInfo.u2nameIndex); 563 dataOutput.writeShort(localVariableTypeInfo.u2signatureIndex); 564 dataOutput.writeShort(localVariableTypeInfo.u2index); 565 } 566 567 568 // Implementations for AnnotationVisitor. 569 570 public void visitAnnotation(Clazz clazz, Annotation annotation) 571 { 572 // Write the annotation type. 573 dataOutput.writeShort(annotation.u2typeIndex); 574 575 // Write the element value pairs. 576 dataOutput.writeShort(annotation.u2elementValuesCount); 577 578 annotation.elementValuesAccept(clazz, this); 579 } 580 581 582 // Implementations for ElementValueVisitor. 583 584 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) 585 { 586 // Write the element name index, if applicable. 587 int u2elementNameIndex = elementValue.u2elementNameIndex; 588 if (u2elementNameIndex != 0) 589 { 590 dataOutput.writeShort(u2elementNameIndex); 591 } 592 593 // Write the tag. 594 dataOutput.writeByte(elementValue.getTag()); 595 596 // Write the actual body. 597 elementValue.accept(clazz, annotation, elementValueBodyWriter); 598 } 599 } 600 601 602 private class StackMapFrameBodyWriter 603 extends SimplifiedVisitor 604 implements StackMapFrameVisitor, 605 VerificationTypeVisitor 606 { 607 public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) 608 { 609 if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) 610 { 611 dataOutput.writeShort(sameZeroFrame.u2offsetDelta); 612 } 613 } 614 615 616 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 617 { 618 if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) 619 { 620 dataOutput.writeShort(sameOneFrame.u2offsetDelta); 621 } 622 623 // Write the verification type of the stack entry. 624 sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 625 } 626 627 628 public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) 629 { 630 dataOutput.writeShort(lessZeroFrame.u2offsetDelta); 631 } 632 633 634 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 635 { 636 dataOutput.writeShort(moreZeroFrame.u2offsetDelta); 637 638 // Write the verification types of the additional local variables. 639 moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 640 } 641 642 643 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 644 { 645 dataOutput.writeShort(fullFrame.u2offsetDelta); 646 647 // Write the verification types of the local variables. 648 dataOutput.writeShort(fullFrame.variablesCount); 649 fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 650 651 // Write the verification types of the stack entries. 652 dataOutput.writeShort(fullFrame.stackCount); 653 fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 654 } 655 656 657 // Implementations for VerificationTypeVisitor. 658 659 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 660 { 661 // Write the verification type tag. 662 dataOutput.writeByte(verificationType.getTag()); 663 664 // Write the actual body. 665 verificationType.accept(clazz, method, codeAttribute, offset, verificationTypeBodyWriter); 666 } 667 } 668 669 670 private class VerificationTypeBodyWriter 671 extends SimplifiedVisitor 672 implements VerificationTypeVisitor 673 { 674 // Implementations for VerificationTypeVisitor. 675 676 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 677 { 678 // Most verification types don't contain any additional information. 679 } 680 681 682 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 683 { 684 dataOutput.writeShort(objectType.u2classIndex); 685 } 686 687 688 public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 689 { 690 dataOutput.writeShort(uninitializedType.u2newInstructionOffset); 691 } 692 } 693 694 695 private class ElementValueBodyWriter 696 extends SimplifiedVisitor 697 implements ElementValueVisitor 698 { 699 // Implementations for ElementValueVisitor. 700 701 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 702 { 703 dataOutput.writeShort(constantElementValue.u2constantValueIndex); 704 } 705 706 707 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 708 { 709 dataOutput.writeShort(enumConstantElementValue.u2typeNameIndex); 710 dataOutput.writeShort(enumConstantElementValue.u2constantNameIndex); 711 } 712 713 714 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 715 { 716 dataOutput.writeShort(classElementValue.u2classInfoIndex); 717 } 718 719 720 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 721 { 722 // Write the annotation. 723 attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue); 724 } 725 726 727 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 728 { 729 // Write the element values. 730 dataOutput.writeShort(arrayElementValue.u2elementValuesCount); 731 732 arrayElementValue.elementValuesAccept(clazz, annotation, attributeBodyWriter); 733 } 734 } 735} 736