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  */
21 package proguard.classfile.io;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.*;
25 import proguard.classfile.attribute.annotation.*;
26 import proguard.classfile.attribute.annotation.target.*;
27 import proguard.classfile.attribute.annotation.target.visitor.*;
28 import proguard.classfile.attribute.annotation.visitor.*;
29 import proguard.classfile.attribute.preverification.*;
30 import proguard.classfile.attribute.preverification.visitor.*;
31 import proguard.classfile.attribute.visitor.*;
32 import proguard.classfile.constant.*;
33 import proguard.classfile.constant.visitor.ConstantVisitor;
34 import proguard.classfile.util.*;
35 import proguard.classfile.visitor.*;
36 
37 import 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  */
45 public class ProgramClassWriter
46 extends      SimplifiedVisitor
47 implements   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      */
ProgramClassWriter(DataOutput dataOutput)64     public ProgramClassWriter(DataOutput dataOutput)
65     {
66         this.dataOutput = new RuntimeDataOutput(dataOutput);
67     }
68 
69 
70     // Implementations for ClassVisitor.
71 
visitProgramClass(ProgramClass programClass)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 
visitLibraryClass(LibraryClass libraryClass)116     public void visitLibraryClass(LibraryClass libraryClass)
117     {
118     }
119 
120 
121     // Implementations for MemberVisitor.
122 
visitProgramField(ProgramClass programClass, ProgramField programField)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 
visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)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 
visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)151     public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
152     {
153     }
154 
155 
156     // Implementations for ConstantVisitor.
157 
visitAnyConstant(Clazz clazz, Constant constant)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 
visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)174         public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
175         {
176             dataOutput.writeInt(integerConstant.u4value);
177         }
178 
179 
visitLongConstant(Clazz clazz, LongConstant longConstant)180         public void visitLongConstant(Clazz clazz, LongConstant longConstant)
181         {
182             dataOutput.writeLong(longConstant.u8value);
183         }
184 
185 
visitFloatConstant(Clazz clazz, FloatConstant floatConstant)186         public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
187         {
188             dataOutput.writeFloat(floatConstant.f4value);
189         }
190 
191 
visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)192         public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
193         {
194             dataOutput.writeDouble(doubleConstant.f8value);
195         }
196 
197 
visitStringConstant(Clazz clazz, StringConstant stringConstant)198         public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
199         {
200             dataOutput.writeShort(stringConstant.u2stringIndex);
201         }
202 
203 
visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)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 
visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)213         public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
214         {
215             dataOutput.writeShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex);
216             dataOutput.writeShort(invokeDynamicConstant.u2nameAndTypeIndex);
217         }
218 
219 
visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)220         public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
221         {
222             dataOutput.writeByte(methodHandleConstant.u1referenceKind);
223             dataOutput.writeShort(methodHandleConstant.u2referenceIndex);
224         }
225 
226 
visitAnyRefConstant(Clazz clazz, RefConstant refConstant)227         public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
228         {
229             dataOutput.writeShort(refConstant.u2classIndex);
230             dataOutput.writeShort(refConstant.u2nameAndTypeIndex);
231         }
232 
233 
visitClassConstant(Clazz clazz, ClassConstant classConstant)234         public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
235         {
236             dataOutput.writeShort(classConstant.u2nameIndex);
237         }
238 
239 
visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)240         public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
241         {
242             dataOutput.writeShort(methodTypeConstant.u2descriptorIndex);
243         }
244 
245 
visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)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 
visitAnyAttribute(Clazz clazz, Attribute attribute)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 
visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)306         public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
307         {
308             // Write the unknown information.
309             dataOutput.write(unknownAttribute.info);
310         }
311 
312 
visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)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 
visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)322         public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
323         {
324             dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex);
325         }
326 
327 
visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)328         public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
329         {
330             dataOutput.writeShort(sourceDirAttribute.u2sourceDirIndex);
331         }
332 
333 
visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)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 
visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)343         public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
344         {
345             dataOutput.writeShort(enclosingMethodAttribute.u2classIndex);
346             dataOutput.writeShort(enclosingMethodAttribute.u2nameAndTypeIndex);
347         }
348 
349 
visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)350         public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
351         {
352             // This attribute does not contain any additional information.
353         }
354 
355 
visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)356         public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
357         {
358             // This attribute does not contain any additional information.
359         }
360 
361 
visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)362         public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
363         {
364             dataOutput.writeShort(signatureAttribute.u2signatureIndex);
365         }
366 
367 
visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)368         public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
369         {
370             dataOutput.writeShort(constantValueAttribute.u2constantValueIndex);
371         }
372 
373 
visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)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 
visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)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 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)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 
visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)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 
visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)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 
visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)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 
visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)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 
visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)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 
visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)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 
visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)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 
visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)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 
visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)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 
visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)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 
visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)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 
visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)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 
visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)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 
visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)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 
visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)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 
visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)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 
visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)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 
visitAnnotation(Clazz clazz, Annotation annotation)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 
visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)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 
visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)637         public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
638         {
639             dataOutput.writeByte(typeParameterTargetInfo.u1typeParameterIndex);
640         }
641 
642 
visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)643         public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
644         {
645             dataOutput.writeShort(superTypeTargetInfo.u2superTypeIndex);
646         }
647 
648 
visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)649         public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
650         {
651             dataOutput.writeByte(typeParameterBoundTargetInfo.u1typeParameterIndex);
652             dataOutput.writeByte(typeParameterBoundTargetInfo.u1boundIndex);
653         }
654 
655 
visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)656         public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
657         {
658         }
659 
660 
visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)661         public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
662         {
663             dataOutput.writeByte(formalParameterTargetInfo.u1formalParameterIndex);
664         }
665 
666 
visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)667         public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
668         {
669             dataOutput.writeShort(throwsTargetInfo.u2throwsTypeIndex);
670         }
671 
672 
visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)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 
visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)682         public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
683         {
684             dataOutput.writeShort(catchTargetInfo.u2exceptionTableIndex);
685         }
686 
687 
visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)688         public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
689         {
690             dataOutput.writeShort(offsetTargetInfo.u2offset);
691         }
692 
693 
visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)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 
visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)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 
visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)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 
visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)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     {
visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)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 
visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)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 
visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)766         public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
767         {
768             dataOutput.writeShort(lessZeroFrame.u2offsetDelta);
769         }
770 
771 
visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)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 
visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)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 
visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)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 
visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)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 
visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)820         public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
821         {
822             dataOutput.writeShort(objectType.u2classIndex);
823         }
824 
825 
visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)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 
visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)839         public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
840         {
841             dataOutput.writeShort(constantElementValue.u2constantValueIndex);
842         }
843 
844 
visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)845         public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
846         {
847             dataOutput.writeShort(enumConstantElementValue.u2typeNameIndex);
848             dataOutput.writeShort(enumConstantElementValue.u2constantNameIndex);
849         }
850 
851 
visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)852         public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
853         {
854             dataOutput.writeShort(classElementValue.u2classInfoIndex);
855         }
856 
857 
visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)858         public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
859         {
860             // Write the annotation.
861             attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue);
862         }
863 
864 
visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)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