1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 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 reading from 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 visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 212 { 213 dataOutput.writeShort(refConstant.u2classIndex); 214 dataOutput.writeShort(refConstant.u2nameAndTypeIndex); 215 } 216 217 218 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 219 { 220 dataOutput.writeShort(classConstant.u2nameIndex); 221 } 222 223 224 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 225 { 226 dataOutput.writeShort(nameAndTypeConstant.u2nameIndex); 227 dataOutput.writeShort(nameAndTypeConstant.u2descriptorIndex); 228 } 229 } 230 231 232 // Implementations for AttributeVisitor. 233 234 public void visitAnyAttribute(Clazz clazz, Attribute attribute) 235 { 236 // Write the attribute name index. 237 dataOutput.writeShort(attribute.u2attributeNameIndex); 238 239 // We'll write the attribute body into an array first, so we can 240 // automatically figure out its length. 241 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 242 243 // Temporarily replace the current data output. 244 RuntimeDataOutput oldDataOutput = dataOutput; 245 dataOutput = new RuntimeDataOutput(new DataOutputStream(byteArrayOutputStream)); 246 247 // Write the attribute body into the array. Note that the 248 // accept method with two dummy null arguments never throws 249 // an UnsupportedOperationException. 250 attribute.accept(clazz, null, null, attributeBodyWriter); 251 252 // Restore the original data output. 253 dataOutput = oldDataOutput; 254 255 // Write the attribute length and body. 256 byte[] info = byteArrayOutputStream.toByteArray(); 257 258 dataOutput.writeInt(info.length); 259 dataOutput.write(info); 260 } 261 262 263 private class AttributeBodyWriter 264 extends SimplifiedVisitor 265 implements AttributeVisitor, 266 InnerClassesInfoVisitor, 267 ExceptionInfoVisitor, 268 StackMapFrameVisitor, 269 VerificationTypeVisitor, 270 LineNumberInfoVisitor, 271 LocalVariableInfoVisitor, 272 LocalVariableTypeInfoVisitor, 273 AnnotationVisitor, 274 ElementValueVisitor 275 { 276 // Implementations for AttributeVisitor. 277 278 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 279 { 280 // Write the unknown information. 281 dataOutput.write(unknownAttribute.info); 282 } 283 284 285 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 286 { 287 dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex); 288 } 289 290 291 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 292 { 293 dataOutput.writeShort(sourceDirAttribute.u2sourceDirIndex); 294 } 295 296 297 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 298 { 299 // Write the inner classes. 300 dataOutput.writeShort(innerClassesAttribute.u2classesCount); 301 302 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 303 } 304 305 306 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 307 { 308 dataOutput.writeShort(enclosingMethodAttribute.u2classIndex); 309 dataOutput.writeShort(enclosingMethodAttribute.u2nameAndTypeIndex); 310 } 311 312 313 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 314 { 315 // This attribute does not contain any additional information. 316 } 317 318 319 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 320 { 321 // This attribute does not contain any additional information. 322 } 323 324 325 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 326 { 327 dataOutput.writeShort(signatureAttribute.u2signatureIndex); 328 } 329 330 331 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 332 { 333 dataOutput.writeShort(constantValueAttribute.u2constantValueIndex); 334 } 335 336 337 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 338 { 339 // Write the exceptions. 340 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTableLength); 341 342 for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) 343 { 344 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTable[index]); 345 } 346 } 347 348 349 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 350 { 351 // Write the stack size and local variable frame size. 352 dataOutput.writeShort(codeAttribute.u2maxStack); 353 dataOutput.writeShort(codeAttribute.u2maxLocals); 354 355 // Write the byte code. 356 dataOutput.writeInt(codeAttribute.u4codeLength); 357 358 dataOutput.write(codeAttribute.code, 0, codeAttribute.u4codeLength); 359 360 // Write the exceptions. 361 dataOutput.writeShort(codeAttribute.u2exceptionTableLength); 362 363 codeAttribute.exceptionsAccept(clazz, method, this); 364 365 // Write the code attributes. 366 dataOutput.writeShort(codeAttribute.u2attributesCount); 367 368 codeAttribute.attributesAccept(clazz, method, ProgramClassWriter.this); 369 } 370 371 372 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 373 { 374 // Write the stack map frames (only full frames, without tag). 375 dataOutput.writeShort(stackMapAttribute.u2stackMapFramesCount); 376 377 stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, stackMapFrameBodyWriter); 378 } 379 380 381 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 382 { 383 // Write the stack map frames. 384 dataOutput.writeShort(stackMapTableAttribute.u2stackMapFramesCount); 385 386 stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 387 } 388 389 390 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 391 { 392 // Write the line numbers. 393 dataOutput.writeShort(lineNumberTableAttribute.u2lineNumberTableLength); 394 395 lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this); 396 } 397 398 399 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 400 { 401 // Write the local variables. 402 dataOutput.writeShort(localVariableTableAttribute.u2localVariableTableLength); 403 404 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 405 } 406 407 408 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 409 { 410 // Write the local variable types. 411 dataOutput.writeShort(localVariableTypeTableAttribute.u2localVariableTypeTableLength); 412 413 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 414 } 415 416 417 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 418 { 419 // Write the annotations. 420 dataOutput.writeShort(annotationsAttribute.u2annotationsCount); 421 422 annotationsAttribute.annotationsAccept(clazz, this); 423 } 424 425 426 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 427 { 428 // Write the parameter annotations. 429 dataOutput.writeByte(parameterAnnotationsAttribute.u2parametersCount); 430 431 for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) 432 { 433 // Write the parameter annotations of the given parameter. 434 int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; 435 Annotation[] annotations = parameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; 436 437 dataOutput.writeShort(u2annotationsCount); 438 439 for (int index = 0; index < u2annotationsCount; index++) 440 { 441 Annotation annotation = annotations[index]; 442 this.visitAnnotation(clazz, annotation); 443 } 444 445 } 446 } 447 448 449 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 450 { 451 // Write the default element value. 452 annotationDefaultAttribute.defaultValue.accept(clazz, null, this); 453 } 454 455 456 // Implementations for InnerClassesInfoVisitor. 457 458 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 459 { 460 dataOutput.writeShort(innerClassesInfo.u2innerClassIndex); 461 dataOutput.writeShort(innerClassesInfo.u2outerClassIndex); 462 dataOutput.writeShort(innerClassesInfo.u2innerNameIndex); 463 dataOutput.writeShort(innerClassesInfo.u2innerClassAccessFlags); 464 } 465 466 467 // Implementations for ExceptionInfoVisitor. 468 469 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 470 { 471 dataOutput.writeShort(exceptionInfo.u2startPC); 472 dataOutput.writeShort(exceptionInfo.u2endPC); 473 dataOutput.writeShort(exceptionInfo.u2handlerPC); 474 dataOutput.writeShort(exceptionInfo.u2catchType); 475 } 476 477 478 // Implementations for StackMapFrameVisitor. 479 480 public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) 481 { 482 // Write the stack map frame tag. 483 dataOutput.writeByte(stackMapFrame.getTag()); 484 485 // Write the actual body. 486 stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameBodyWriter); 487 } 488 489 490 // Implementations for LineNumberInfoVisitor. 491 492 public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 493 { 494 dataOutput.writeShort(lineNumberInfo.u2startPC); 495 dataOutput.writeShort(lineNumberInfo.u2lineNumber); 496 } 497 498 499 // Implementations for LocalVariableInfoVisitor. 500 501 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 502 { 503 dataOutput.writeShort(localVariableInfo.u2startPC); 504 dataOutput.writeShort(localVariableInfo.u2length); 505 dataOutput.writeShort(localVariableInfo.u2nameIndex); 506 dataOutput.writeShort(localVariableInfo.u2descriptorIndex); 507 dataOutput.writeShort(localVariableInfo.u2index); 508 } 509 510 511 // Implementations for LocalVariableTypeInfoVisitor. 512 513 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 514 { 515 dataOutput.writeShort(localVariableTypeInfo.u2startPC); 516 dataOutput.writeShort(localVariableTypeInfo.u2length); 517 dataOutput.writeShort(localVariableTypeInfo.u2nameIndex); 518 dataOutput.writeShort(localVariableTypeInfo.u2signatureIndex); 519 dataOutput.writeShort(localVariableTypeInfo.u2index); 520 } 521 522 523 // Implementations for AnnotationVisitor. 524 525 public void visitAnnotation(Clazz clazz, Annotation annotation) 526 { 527 // Write the annotation type. 528 dataOutput.writeShort(annotation.u2typeIndex); 529 530 // Write the element value pairs. 531 dataOutput.writeShort(annotation.u2elementValuesCount); 532 533 annotation.elementValuesAccept(clazz, this); 534 } 535 536 537 // Implementations for ElementValueVisitor. 538 539 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) 540 { 541 // Write the element name index, if applicable. 542 int u2elementNameIndex = elementValue.u2elementNameIndex; 543 if (u2elementNameIndex != 0) 544 { 545 dataOutput.writeShort(u2elementNameIndex); 546 } 547 548 // Write the tag. 549 dataOutput.writeByte(elementValue.getTag()); 550 551 // Write the actual body. 552 elementValue.accept(clazz, annotation, elementValueBodyWriter); 553 } 554 } 555 556 557 private class StackMapFrameBodyWriter 558 extends SimplifiedVisitor 559 implements StackMapFrameVisitor, 560 VerificationTypeVisitor 561 { 562 public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) 563 { 564 if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) 565 { 566 dataOutput.writeShort(sameZeroFrame.u2offsetDelta); 567 } 568 } 569 570 571 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 572 { 573 if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) 574 { 575 dataOutput.writeShort(sameOneFrame.u2offsetDelta); 576 } 577 578 // Write the verification type of the stack entry. 579 sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 580 } 581 582 583 public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) 584 { 585 dataOutput.writeShort(lessZeroFrame.u2offsetDelta); 586 } 587 588 589 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 590 { 591 dataOutput.writeShort(moreZeroFrame.u2offsetDelta); 592 593 // Write the verification types of the additional local variables. 594 moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 595 } 596 597 598 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 599 { 600 dataOutput.writeShort(fullFrame.u2offsetDelta); 601 602 // Write the verification types of the local variables. 603 dataOutput.writeShort(fullFrame.variablesCount); 604 fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 605 606 // Write the verification types of the stack entries. 607 dataOutput.writeShort(fullFrame.stackCount); 608 fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 609 } 610 611 612 // Implementations for VerificationTypeVisitor. 613 614 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 615 { 616 // Write the verification type tag. 617 dataOutput.writeByte(verificationType.getTag()); 618 619 // Write the actual body. 620 verificationType.accept(clazz, method, codeAttribute, offset, verificationTypeBodyWriter); 621 } 622 } 623 624 625 private class VerificationTypeBodyWriter 626 extends SimplifiedVisitor 627 implements VerificationTypeVisitor 628 { 629 // Implementations for VerificationTypeVisitor. 630 631 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 632 { 633 // Most verification types don't contain any additional information. 634 } 635 636 637 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 638 { 639 dataOutput.writeShort(objectType.u2classIndex); 640 } 641 642 643 public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 644 { 645 dataOutput.writeShort(uninitializedType.u2newInstructionOffset); 646 } 647 } 648 649 650 private class ElementValueBodyWriter 651 extends SimplifiedVisitor 652 implements ElementValueVisitor 653 { 654 // Implementations for ElementValueVisitor. 655 656 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 657 { 658 dataOutput.writeShort(constantElementValue.u2constantValueIndex); 659 } 660 661 662 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 663 { 664 dataOutput.writeShort(enumConstantElementValue.u2typeNameIndex); 665 dataOutput.writeShort(enumConstantElementValue.u2constantNameIndex); 666 } 667 668 669 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 670 { 671 dataOutput.writeShort(classElementValue.u2classInfoIndex); 672 } 673 674 675 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 676 { 677 // Write the annotation. 678 attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue); 679 } 680 681 682 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 683 { 684 // Write the element values. 685 dataOutput.writeShort(arrayElementValue.u2elementValuesCount); 686 687 arrayElementValue.elementValuesAccept(clazz, annotation, attributeBodyWriter); 688 } 689 } 690} 691