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