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