src/share/classes/com/sun/tools/classfile/ClassWriter.java

Wed, 02 Jun 2010 19:08:47 -0700

author
darcy
date
Wed, 02 Jun 2010 19:08:47 -0700
changeset 575
9a7c998bf2fc
parent 554
9d9f26857129
child 581
f2fdd52e4e87
permissions
-rw-r--r--

6933147: Provided new utility visitors supporting SourceVersion.RELEASE_7
Reviewed-by: jjg

     2 /*
     3  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     8  * published by the Free Software Foundation.  Oracle designates this
     9  * particular file as subject to the "Classpath" exception as provided
    10  * by Oracle in the LICENSE file that accompanied this code.
    11  *
    12  * This code 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
    15  * version 2 for more details (a copy is included in the LICENSE file that
    16  * accompanied this code).
    17  *
    18  * You should have received a copy of the GNU General Public License version
    19  * 2 along with this work; if not, write to the Free Software Foundation,
    20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    21  *
    22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    23  * or visit www.oracle.com if you need additional information or have any
    24  * questions.
    25  */
    27 package com.sun.tools.classfile;
    29 import java.io.ByteArrayOutputStream;
    30 import java.io.DataOutputStream;
    31 import java.io.File;
    32 import java.io.FileOutputStream;
    33 import java.io.IOException;
    34 import java.io.OutputStream;
    36 import static com.sun.tools.classfile.Annotation.*;
    37 import static com.sun.tools.classfile.ConstantPool.*;
    38 import static com.sun.tools.classfile.StackMapTable_attribute.*;
    39 import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
    41 /**
    42  * Write a ClassFile data structure to a file or stream.
    43  *
    44  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    45  *  you write code that depends on this, you do so at your own risk.
    46  *  This code and its internal interfaces are subject to change or
    47  *  deletion without notice.</b>
    48  */
    49 public class ClassWriter {
    50     public ClassWriter() {
    51         attributeWriter = new AttributeWriter();
    52         constantPoolWriter = new ConstantPoolWriter();
    53         out = new ClassOutputStream();
    54     }
    56     /**
    57      * Write a ClassFile data structure to a file.
    58      */
    59     public void write(ClassFile classFile, File f) throws IOException {
    60         FileOutputStream f_out = new FileOutputStream(f);
    61         try {
    62             write(classFile, f_out);
    63         } finally {
    64             f_out.close();
    65         }
    66     }
    68     /**
    69      * Write a ClassFile data structure to a stream.
    70      */
    71     public void write(ClassFile classFile, OutputStream s) throws IOException {
    72         this.classFile = classFile;
    73         out.reset();
    74         write();
    75         out.writeTo(s);
    76     }
    78     protected void write() throws IOException {
    79         writeHeader();
    80         writeConstantPool();
    81         writeAccessFlags(classFile.access_flags);
    82         writeClassInfo();
    83         writeFields();
    84         writeMethods();
    85         writeAttributes(classFile.attributes);
    86     }
    88     protected void writeHeader() {
    89         out.writeInt(classFile.magic);
    90         out.writeShort(classFile.minor_version);
    91         out.writeShort(classFile.major_version);
    92     }
    94     protected void writeAccessFlags(AccessFlags flags) {
    95         out.writeShort(flags.flags);
    96     }
    98     protected void writeAttributes(Attributes attributes) {
    99         int size = attributes.size();
   100         out.writeShort(size);
   101         for (Attribute attr: attributes)
   102             attributeWriter.write(attr, out);
   103     }
   105     protected void writeClassInfo() {
   106         out.writeShort(classFile.this_class);
   107         out.writeShort(classFile.super_class);
   108         int[] interfaces = classFile.interfaces;
   109         out.writeShort(interfaces.length);
   110         for (int i: interfaces)
   111             out.writeShort(i);
   112     }
   114     protected void writeDescriptor(Descriptor d) {
   115         out.writeShort(d.index);
   116     }
   118     protected void writeConstantPool() {
   119         ConstantPool pool = classFile.constant_pool;
   120         int size = pool.size();
   121         out.writeShort(size);
   122         for (CPInfo cpInfo: pool.entries())
   123             constantPoolWriter.write(cpInfo, out);
   124     }
   126     protected void writeFields() throws IOException {
   127         Field[] fields = classFile.fields;
   128         out.writeShort(fields.length);
   129         for (Field f: fields)
   130             writeField(f);
   131     }
   133     protected void writeField(Field f) throws IOException {
   134         writeAccessFlags(f.access_flags);
   135         out.writeShort(f.name_index);
   136         writeDescriptor(f.descriptor);
   137         writeAttributes(f.attributes);
   138     }
   140     protected void writeMethods() throws IOException {
   141         Method[] methods = classFile.methods;
   142         out.writeShort(methods.length);
   143         for (Method m: methods) {
   144             writeMethod(m);
   145         }
   146     }
   148     protected void writeMethod(Method m) throws IOException {
   149         writeAccessFlags(m.access_flags);
   150         out.writeShort(m.name_index);
   151         writeDescriptor(m.descriptor);
   152         writeAttributes(m.attributes);
   153     }
   155     protected ClassFile classFile;
   156     protected ClassOutputStream out;
   157     protected AttributeWriter attributeWriter;
   158     protected ConstantPoolWriter constantPoolWriter;
   160     /**
   161      * Subtype of ByteArrayOutputStream with the convenience methods of
   162      * a DataOutputStream. Since ByteArrayOutputStream does not throw
   163      * IOException, there are no exceptions from the additional
   164      * convenience methods either,
   165      */
   166     protected static class ClassOutputStream extends ByteArrayOutputStream {
   167         public ClassOutputStream() {
   168             d = new DataOutputStream(this);
   169         }
   171         public void writeByte(int value) {
   172             try {
   173                 d.writeByte(value);
   174             } catch (IOException ignore) {
   175             }
   176         }
   178         public void writeShort(int value) {
   179             try {
   180                 d.writeShort(value);
   181             } catch (IOException ignore) {
   182             }
   183         }
   185         public void writeInt(int value) {
   186             try {
   187                 d.writeInt(value);
   188             } catch (IOException ignore) {
   189             }
   190         }
   192         public void writeLong(long value) {
   193             try {
   194                 d.writeLong(value);
   195             } catch (IOException ignore) {
   196             }
   197         }
   199         public void writeFloat(float value) {
   200             try {
   201                 d.writeFloat(value);
   202             } catch (IOException ignore) {
   203             }
   204         }
   206         public void writeDouble(double value) {
   207             try {
   208                 d.writeDouble(value);
   209             } catch (IOException ignore) {
   210             }
   211         }
   213         public void writeUTF(String value) {
   214             try {
   215                 d.writeUTF(value);
   216             } catch (IOException ignore) {
   217             }
   218         }
   220         public void writeTo(ClassOutputStream s) {
   221             try {
   222                 super.writeTo(s);
   223             } catch (IOException ignore) {
   224             }
   225         }
   227         private DataOutputStream d;
   228     }
   230     /**
   231      * Writer for the entries in the constant pool.
   232      */
   233     protected static class ConstantPoolWriter
   234            implements ConstantPool.Visitor<Integer,ClassOutputStream> {
   235         protected int write(CPInfo info, ClassOutputStream out) {
   236             out.writeByte(info.getTag());
   237             return info.accept(this, out);
   238         }
   240         public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {
   241             out.writeShort(info.name_index);
   242             return 1;
   243         }
   245         public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {
   246             out.writeDouble(info.value);
   247             return 2;
   248         }
   250         public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {
   251             writeRef(info, out);
   252             return 1;
   253         }
   255         public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {
   256             out.writeFloat(info.value);
   257             return 1;
   258         }
   260         public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {
   261             out.writeInt(info.value);
   262             return 1;
   263         }
   265         public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {
   266             writeRef(info, out);
   267             return 1;
   268         }
   270         public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
   271             out.writeLong(info.value);
   272             return 2;
   273         }
   275         public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {
   276             out.writeShort(info.name_index);
   277             out.writeShort(info.type_index);
   278             return 1;
   279         }
   281         public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
   282             return writeRef(info, out);
   283         }
   285         public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {
   286             out.writeShort(info.string_index);
   287             return 1;
   288         }
   290         public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {
   291             out.writeUTF(info.value);
   292             return 1;
   293         }
   295         protected Integer writeRef(CPRefInfo info, ClassOutputStream out) {
   296             out.writeShort(info.class_index);
   297             out.writeShort(info.name_and_type_index);
   298             return 1;
   299         }
   300     }
   302     /**
   303      * Writer for the different types of attribute.
   304      */
   305     protected static class AttributeWriter implements Attribute.Visitor<Void,ClassOutputStream> {
   306         public void write(Attributes attributes, ClassOutputStream out) {
   307             int size = attributes.size();
   308             out.writeShort(size);
   309             for (Attribute a: attributes)
   310                 write(a, out);
   311         }
   313         // Note: due to the use of shared resources, this method is not reentrant.
   314         public void write(Attribute attr, ClassOutputStream out) {
   315             out.writeShort(attr.attribute_name_index);
   316             sharedOut.reset();
   317             attr.accept(this, sharedOut);
   318             out.writeInt(sharedOut.size());
   319             sharedOut.writeTo(out);
   320         }
   322         protected ClassOutputStream sharedOut = new ClassOutputStream();
   323         protected AnnotationWriter annotationWriter = new AnnotationWriter();
   325         public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {
   326             out.write(attr.info, 0, attr.info.length);
   327             return null;
   328         }
   330         public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {
   331             annotationWriter.write(attr.default_value, out);
   332             return null;
   333         }
   335         public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
   336             out.writeShort(attr.character_range_table.length);
   337             for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
   338                 writeCharacterRangeTableEntry(e, out);
   339             return null;
   340         }
   342         protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) {
   343             out.writeShort(entry.start_pc);
   344             out.writeShort(entry.end_pc);
   345             out.writeInt(entry.character_range_start);
   346             out.writeInt(entry.character_range_end);
   347             out.writeShort(entry.flags);
   348         }
   350         public Void visitCode(Code_attribute attr, ClassOutputStream out) {
   351             out.writeShort(attr.max_stack);
   352             out.writeShort(attr.max_locals);
   353             out.writeInt(attr.code.length);
   354             out.write(attr.code, 0, attr.code.length);
   355             out.writeShort(attr.exception_table.length);
   356             for (Code_attribute.Exception_data e: attr.exception_table)
   357                 writeExceptionTableEntry(e, out);
   358             new AttributeWriter().write(attr.attributes, out);
   359             return null;
   360         }
   362         protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) {
   363             out.writeShort(exception_data.start_pc);
   364             out.writeShort(exception_data.end_pc);
   365             out.writeShort(exception_data.handler_pc);
   366             out.writeShort(exception_data.catch_type);
   367         }
   369         public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {
   370             out.writeShort(attr.compilationID_index);
   371             return null;
   372         }
   374         public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {
   375             out.writeShort(attr.constantvalue_index);
   376             return null;
   377         }
   379         public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {
   380             return null;
   381         }
   383         public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {
   384             out.writeShort(attr.class_index);
   385             out.writeShort(attr.method_index);
   386             return null;
   387         }
   389         public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {
   390             out.writeShort(attr.exception_index_table.length);
   391             for (int i: attr.exception_index_table)
   392                 out.writeShort(i);
   393             return null;
   394         }
   396         public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {
   397             out.writeShort(attr.classes.length);
   398             for (InnerClasses_attribute.Info info: attr.classes)
   399                 writeInnerClassesInfo(info, out);
   400             return null;
   401         }
   403         protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {
   404             out.writeShort(info.inner_class_info_index);
   405             out.writeShort(info.outer_class_info_index);
   406             out.writeShort(info.inner_name_index);
   407             writeAccessFlags(info.inner_class_access_flags, out);
   408         }
   410         public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {
   411             out.writeShort(attr.line_number_table.length);
   412             for (LineNumberTable_attribute.Entry e: attr.line_number_table)
   413                 writeLineNumberTableEntry(e, out);
   414             return null;
   415         }
   417         protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) {
   418             out.writeShort(entry.start_pc);
   419             out.writeShort(entry.line_number);
   420         }
   422         public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {
   423             out.writeShort(attr.local_variable_table.length);
   424             for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)
   425                 writeLocalVariableTableEntry(e, out);
   426             return null;
   427         }
   429         protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) {
   430             out.writeShort(entry.start_pc);
   431             out.writeShort(entry.length);
   432             out.writeShort(entry.name_index);
   433             out.writeShort(entry.descriptor_index);
   434             out.writeShort(entry.index);
   435         }
   437         public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {
   438             out.writeShort(attr.local_variable_table.length);
   439             for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)
   440                 writeLocalVariableTypeTableEntry(e, out);
   441             return null;
   442         }
   444         protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) {
   445             out.writeShort(entry.start_pc);
   446             out.writeShort(entry.length);
   447             out.writeShort(entry.name_index);
   448             out.writeShort(entry.signature_index);
   449             out.writeShort(entry.index);
   450         }
   452         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
   453             annotationWriter.write(attr.annotations, out);
   454             return null;
   455         }
   457         public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
   458             annotationWriter.write(attr.annotations, out);
   459             return null;
   460         }
   462         public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
   463             annotationWriter.write(attr.annotations, out);
   464             return null;
   465         }
   467         public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
   468             annotationWriter.write(attr.annotations, out);
   469             return null;
   470         }
   472         public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
   473             out.writeByte(attr.parameter_annotations.length);
   474             for (Annotation[] annos: attr.parameter_annotations)
   475                 annotationWriter.write(annos, out);
   476             return null;
   477         }
   479         public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
   480             out.writeByte(attr.parameter_annotations.length);
   481             for (Annotation[] annos: attr.parameter_annotations)
   482                 annotationWriter.write(annos, out);
   483             return null;
   484         }
   486         public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
   487             out.writeShort(attr.signature_index);
   488             return null;
   489         }
   491         public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
   492             out.write(attr.debug_extension, 0, attr.debug_extension.length);
   493             return null;
   494         }
   496         public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
   497             out.writeShort(attr.sourcefile_index);
   498             return null;
   499         }
   501         public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
   502             out.writeShort(attr.sourceID_index);
   503             return null;
   504         }
   506         public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
   507             if (stackMapWriter == null)
   508                 stackMapWriter = new StackMapTableWriter();
   510             out.writeShort(attr.entries.length);
   511             for (stack_map_frame f: attr.entries)
   512                 stackMapWriter.write(f, out);
   513             return null;
   514         }
   516         public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
   517             if (stackMapWriter == null)
   518                 stackMapWriter = new StackMapTableWriter();
   520             out.writeShort(attr.entries.length);
   521             for (stack_map_frame f: attr.entries)
   522                 stackMapWriter.write(f, out);
   523             return null;
   524         }
   526         public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
   527             return null;
   528         }
   530         protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
   531             sharedOut.writeShort(flags.flags);
   532         }
   534         protected StackMapTableWriter stackMapWriter;
   535     }
   537     /**
   538      * Writer for the frames of StackMap and StackMapTable attributes.
   539      */
   540     protected static class StackMapTableWriter
   541             implements stack_map_frame.Visitor<Void,ClassOutputStream> {
   543         public void write(stack_map_frame frame, ClassOutputStream out) {
   544             out.write(frame.frame_type);
   545             frame.accept(this, out);
   546         }
   548         public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
   549             return null;
   550         }
   552         public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
   553             writeVerificationTypeInfo(frame.stack[0], out);
   554             return null;
   555         }
   557         public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
   558             out.writeShort(frame.offset_delta);
   559             writeVerificationTypeInfo(frame.stack[0], out);
   560             return null;
   561         }
   563         public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
   564             out.writeShort(frame.offset_delta);
   565             return null;
   566         }
   568         public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
   569             out.writeShort(frame.offset_delta);
   570             return null;
   571         }
   573         public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
   574             out.writeShort(frame.offset_delta);
   575             for (verification_type_info l: frame.locals)
   576                 writeVerificationTypeInfo(l, out);
   577             return null;
   578         }
   580         public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
   581             out.writeShort(frame.offset_delta);
   582             out.writeShort(frame.locals.length);
   583             for (verification_type_info l: frame.locals)
   584                 writeVerificationTypeInfo(l, out);
   585             out.writeShort(frame.stack.length);
   586             for (verification_type_info s: frame.stack)
   587                 writeVerificationTypeInfo(s, out);
   588             return null;
   589         }
   591         protected void writeVerificationTypeInfo(verification_type_info info,
   592                 ClassOutputStream out)  {
   593             out.write(info.tag);
   594             switch (info.tag) {
   595             case ITEM_Top:
   596             case ITEM_Integer:
   597             case ITEM_Float:
   598             case ITEM_Long:
   599             case ITEM_Double:
   600             case ITEM_Null:
   601             case ITEM_UninitializedThis:
   602                 break;
   604             case ITEM_Object:
   605                 Object_variable_info o = (Object_variable_info) info;
   606                 out.writeShort(o.cpool_index);
   607                 break;
   609             case ITEM_Uninitialized:
   610                 Uninitialized_variable_info u = (Uninitialized_variable_info) info;
   611                 out.writeShort(u.offset);
   612                 break;
   614             default:
   615                 throw new Error();
   616             }
   617         }
   618     }
   620     /**
   621      * Writer for annotations and the values they contain.
   622      */
   623     protected static class AnnotationWriter
   624             implements Annotation.element_value.Visitor<Void,ClassOutputStream> {
   625         public void write(Annotation[] annos, ClassOutputStream out) {
   626             out.writeShort(annos.length);
   627             for (Annotation anno: annos)
   628                 write(anno, out);
   629         }
   631         public void write(ExtendedAnnotation[] annos, ClassOutputStream out) {
   632             out.writeShort(annos.length);
   633             for (ExtendedAnnotation anno: annos)
   634                 write(anno, out);
   635         }
   637         public void write(Annotation anno, ClassOutputStream out) {
   638             out.writeShort(anno.type_index);
   639             out.writeShort(anno.element_value_pairs.length);
   640             for (element_value_pair p: anno.element_value_pairs)
   641                 write(p, out);
   642         }
   644         public void write(ExtendedAnnotation anno, ClassOutputStream out) {
   645             write(anno.annotation, out);
   646             write(anno.position, out);
   647         }
   649         public void write(element_value_pair pair, ClassOutputStream out) {
   650             out.writeShort(pair.element_name_index);
   651             write(pair.value, out);
   652         }
   654         public void write(element_value ev, ClassOutputStream out) {
   655             out.writeByte(ev.tag);
   656             ev.accept(this, out);
   657         }
   659         public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
   660             out.writeShort(ev.const_value_index);
   661             return null;
   662         }
   664         public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
   665             out.writeShort(ev.type_name_index);
   666             out.writeShort(ev.const_name_index);
   667             return null;
   668         }
   670         public Void visitClass(Class_element_value ev, ClassOutputStream out) {
   671             out.writeShort(ev.class_info_index);
   672             return null;
   673         }
   675         public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
   676             write(ev.annotation_value, out);
   677             return null;
   678         }
   680         public Void visitArray(Array_element_value ev, ClassOutputStream out) {
   681             out.writeShort(ev.num_values);
   682             for (element_value v: ev.values)
   683                 write(v, out);
   684             return null;
   685         }
   687         private void write(ExtendedAnnotation.Position p, ClassOutputStream out) {
   688             out.writeByte(p.type.targetTypeValue());
   689             switch (p.type) {
   690             // type case
   691             case TYPECAST:
   692             case TYPECAST_GENERIC_OR_ARRAY:
   693             // object creation
   694             case INSTANCEOF:
   695             case INSTANCEOF_GENERIC_OR_ARRAY:
   696             // new expression
   697             case NEW:
   698             case NEW_GENERIC_OR_ARRAY:
   699             case NEW_TYPE_ARGUMENT:
   700             case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
   701                 out.writeShort(p.offset);
   702                 break;
   703              // local variable
   704             case LOCAL_VARIABLE:
   705             case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
   706                 int table_length = p.lvarOffset.length;
   707                 out.writeShort(table_length);
   708                 for (int i = 0; i < table_length; ++i) {
   709                     out.writeShort(1);  // for table length
   710                     out.writeShort(p.lvarOffset[i]);
   711                     out.writeShort(p.lvarLength[i]);
   712                     out.writeShort(p.lvarIndex[i]);
   713                 }
   714                 break;
   715              // method receiver
   716             case METHOD_RECEIVER:
   717                 // Do nothing
   718                 break;
   719             // type parameters
   720             case CLASS_TYPE_PARAMETER:
   721             case METHOD_TYPE_PARAMETER:
   722                 out.writeByte(p.parameter_index);
   723                 break;
   724             // type parameters bounds
   725             case CLASS_TYPE_PARAMETER_BOUND:
   726             case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
   727             case METHOD_TYPE_PARAMETER_BOUND:
   728             case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
   729                 out.writeByte(p.parameter_index);
   730                 out.writeByte(p.bound_index);
   731                 break;
   732              // wildcards
   733             case WILDCARD_BOUND:
   734             case WILDCARD_BOUND_GENERIC_OR_ARRAY:
   735                 write(p.wildcard_position, out);
   736                 break;
   737             // Class extends and implements clauses
   738             case CLASS_EXTENDS:
   739             case CLASS_EXTENDS_GENERIC_OR_ARRAY:
   740                 out.writeByte(p.type_index);
   741                 break;
   742             // throws
   743             case THROWS:
   744                 out.writeByte(p.type_index);
   745                 break;
   746             case CLASS_LITERAL:
   747             case CLASS_LITERAL_GENERIC_OR_ARRAY:
   748                 out.writeShort(p.offset);
   749                 break;
   750             // method parameter: not specified
   751             case METHOD_PARAMETER_GENERIC_OR_ARRAY:
   752                 out.writeByte(p.parameter_index);
   753                 break;
   754             // method type argument: wasn't specified
   755             case METHOD_TYPE_ARGUMENT:
   756             case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
   757                 out.writeShort(p.offset);
   758                 out.writeByte(p.type_index);
   759                 break;
   760             // We don't need to worry abut these
   761             case METHOD_RETURN_GENERIC_OR_ARRAY:
   762             case FIELD_GENERIC_OR_ARRAY:
   763                 break;
   764             case UNKNOWN:
   765                 break;
   766             default:
   767                 throw new AssertionError("unknown type: " + p);
   768             }
   770             // Append location data for generics/arrays.
   771             if (p.type.hasLocation()) {
   772                 out.writeShort(p.location.size());
   773                 for (int i : p.location)
   774                     out.writeByte((byte)i);
   775             }
   776         }
   777     }
   778 }

mercurial