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