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

Fri, 26 Jun 2009 18:51:39 -0700

author
jjg
date
Fri, 26 Jun 2009 18:51:39 -0700
changeset 308
03944ee4fac4
parent 282
fc634a593812
child 352
160d7a994e69
permissions
-rw-r--r--

6843077: JSR 308: Annotations on types
Reviewed-by: jjg, mcimadamore, darcy
Contributed-by: mernst@cs.washington.edu, mali@csail.mit.edu, mpapi@csail.mit.edu

     2 /*
     3  * Copyright 2008 Sun Microsystems, Inc.  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.  Sun designates this
     9  * particular file as subject to the "Classpath" exception as provided
    10  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    23  * CA 95054 USA or visit www.sun.com if you need additional information or
    24  * have any 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.writeByte(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 visitModule(Module_attribute attr, ClassOutputStream out) {
   453             out.writeShort(attr.module_name);
   454             return null;
   455         }
   457         public Void visitModuleExportTable(ModuleExportTable_attribute attr, ClassOutputStream out) {
   458             out.writeShort(attr.export_type_table.length);
   459             for (int i: attr.export_type_table)
   460                 out.writeShort(i);
   461             return null;
   462         }
   464         public Void visitModuleMemberTable(ModuleMemberTable_attribute attr, ClassOutputStream out) {
   465             out.writeShort(attr.package_member_table.length);
   466             for (int i: attr.package_member_table)
   467                 out.writeShort(i);
   468             return null;
   469         }
   471         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
   472             annotationWriter.write(attr.annotations, out);
   473             return null;
   474         }
   476         public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
   477             annotationWriter.write(attr.annotations, out);
   478             return null;
   479         }
   481         public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
   482             annotationWriter.write(attr.annotations, out);
   483             return null;
   484         }
   486         public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
   487             annotationWriter.write(attr.annotations, out);
   488             return null;
   489         }
   491         public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
   492             out.writeByte(attr.parameter_annotations.length);
   493             for (Annotation[] annos: attr.parameter_annotations)
   494                 annotationWriter.write(annos, out);
   495             return null;
   496         }
   498         public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
   499             out.writeByte(attr.parameter_annotations.length);
   500             for (Annotation[] annos: attr.parameter_annotations)
   501                 annotationWriter.write(annos, out);
   502             return null;
   503         }
   505         public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
   506             out.writeShort(attr.signature_index);
   507             return null;
   508         }
   510         public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
   511             out.write(attr.debug_extension, 0, attr.debug_extension.length);
   512             return null;
   513         }
   515         public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
   516             out.writeShort(attr.sourcefile_index);
   517             return null;
   518         }
   520         public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
   521             out.writeShort(attr.sourceID_index);
   522             return null;
   523         }
   525         public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
   526             if (stackMapWriter == null)
   527                 stackMapWriter = new StackMapTableWriter();
   529             out.writeShort(attr.entries.length);
   530             for (stack_map_frame f: attr.entries)
   531                 stackMapWriter.write(f, out);
   532             return null;
   533         }
   535         public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
   536             if (stackMapWriter == null)
   537                 stackMapWriter = new StackMapTableWriter();
   539             out.writeShort(attr.entries.length);
   540             for (stack_map_frame f: attr.entries)
   541                 stackMapWriter.write(f, out);
   542             return null;
   543         }
   545         public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
   546             return null;
   547         }
   549         protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
   550             sharedOut.writeShort(flags.flags);
   551         }
   553         protected StackMapTableWriter stackMapWriter;
   554     }
   556     /**
   557      * Writer for the frames of StackMap and StackMapTable attributes.
   558      */
   559     protected static class StackMapTableWriter
   560             implements stack_map_frame.Visitor<Void,ClassOutputStream> {
   562         public void write(stack_map_frame frame, ClassOutputStream out) {
   563             out.write(frame.frame_type);
   564             frame.accept(this, out);
   565         }
   567         public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
   568             return null;
   569         }
   571         public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
   572             writeVerificationTypeInfo(frame.stack[0], out);
   573             return null;
   574         }
   576         public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
   577             out.writeShort(frame.offset_delta);
   578             writeVerificationTypeInfo(frame.stack[0], out);
   579             return null;
   580         }
   582         public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
   583             out.writeShort(frame.offset_delta);
   584             return null;
   585         }
   587         public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
   588             out.writeShort(frame.offset_delta);
   589             return null;
   590         }
   592         public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
   593             out.writeShort(frame.offset_delta);
   594             for (verification_type_info l: frame.locals)
   595                 writeVerificationTypeInfo(l, out);
   596             return null;
   597         }
   599         public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
   600             out.writeShort(frame.offset_delta);
   601             out.writeShort(frame.locals.length);
   602             for (verification_type_info l: frame.locals)
   603                 writeVerificationTypeInfo(l, out);
   604             out.writeShort(frame.stack.length);
   605             for (verification_type_info s: frame.stack)
   606                 writeVerificationTypeInfo(s, out);
   607             return null;
   608         }
   610         protected void writeVerificationTypeInfo(verification_type_info info,
   611                 ClassOutputStream out)  {
   612             out.write(info.tag);
   613             switch (info.tag) {
   614             case ITEM_Top:
   615             case ITEM_Integer:
   616             case ITEM_Float:
   617             case ITEM_Long:
   618             case ITEM_Double:
   619             case ITEM_Null:
   620             case ITEM_UninitializedThis:
   621                 break;
   623             case ITEM_Object:
   624                 Object_variable_info o = (Object_variable_info) info;
   625                 out.writeShort(o.cpool_index);
   626                 break;
   628             case ITEM_Uninitialized:
   629                 Uninitialized_variable_info u = (Uninitialized_variable_info) info;
   630                 out.writeShort(u.offset);
   631                 break;
   633             default:
   634                 throw new Error();
   635             }
   636         }
   637     }
   639     /**
   640      * Writer for annotations and the values they contain.
   641      */
   642     protected static class AnnotationWriter
   643             implements Annotation.element_value.Visitor<Void,ClassOutputStream> {
   644         public void write(Annotation[] annos, ClassOutputStream out) {
   645             out.writeShort(annos.length);
   646             for (Annotation anno: annos)
   647                 write(anno, out);
   648         }
   650         public void write(ExtendedAnnotation[] annos, ClassOutputStream out) {
   651             out.writeShort(annos.length);
   652             for (ExtendedAnnotation anno: annos)
   653                 write(anno, out);
   654         }
   656         public void write(Annotation anno, ClassOutputStream out) {
   657             out.writeShort(anno.type_index);
   658             out.writeShort(anno.element_value_pairs.length);
   659             for (element_value_pair p: anno.element_value_pairs)
   660                 write(p, out);
   661         }
   663         public void write(ExtendedAnnotation anno, ClassOutputStream out) {
   664             write(anno.annotation, out);
   665             write(anno.position, out);
   666         }
   668         public void write(element_value_pair pair, ClassOutputStream out) {
   669             out.writeShort(pair.element_name_index);
   670             write(pair.value, out);
   671         }
   673         public void write(element_value ev, ClassOutputStream out) {
   674             out.writeByte(ev.tag);
   675             ev.accept(this, out);
   676         }
   678         public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
   679             out.writeShort(ev.const_value_index);
   680             return null;
   681         }
   683         public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
   684             out.writeShort(ev.type_name_index);
   685             out.writeShort(ev.const_name_index);
   686             return null;
   687         }
   689         public Void visitClass(Class_element_value ev, ClassOutputStream out) {
   690             out.writeShort(ev.class_info_index);
   691             return null;
   692         }
   694         public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
   695             write(ev.annotation_value, out);
   696             return null;
   697         }
   699         public Void visitArray(Array_element_value ev, ClassOutputStream out) {
   700             out.writeShort(ev.num_values);
   701             for (element_value v: ev.values)
   702                 write(v, out);
   703             return null;
   704         }
   706         private void write(ExtendedAnnotation.Position p, ClassOutputStream out) {
   707             out.writeByte(p.type.targetTypeValue());
   708             switch (p.type) {
   709             // type case
   710             case TYPECAST:
   711             case TYPECAST_GENERIC_OR_ARRAY:
   712             // object creation
   713             case INSTANCEOF:
   714             case INSTANCEOF_GENERIC_OR_ARRAY:
   715             // new expression
   716             case NEW:
   717             case NEW_GENERIC_OR_ARRAY:
   718             case NEW_TYPE_ARGUMENT:
   719             case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
   720                 out.writeShort(p.offset);
   721                 break;
   722              // local variable
   723             case LOCAL_VARIABLE:
   724             case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
   725                 int table_length = p.lvarOffset.length;
   726                 out.writeShort(table_length);
   727                 for (int i = 0; i < table_length; ++i) {
   728                     out.writeShort(1);  // for table length
   729                     out.writeShort(p.lvarOffset[i]);
   730                     out.writeShort(p.lvarLength[i]);
   731                     out.writeShort(p.lvarIndex[i]);
   732                 }
   733                 break;
   734              // method receiver
   735             case METHOD_RECEIVER:
   736                 // Do nothing
   737                 break;
   738             // type parameters
   739             case CLASS_TYPE_PARAMETER:
   740             case METHOD_TYPE_PARAMETER:
   741                 out.writeByte(p.parameter_index);
   742                 break;
   743             // type parameters bounds
   744             case CLASS_TYPE_PARAMETER_BOUND:
   745             case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
   746             case METHOD_TYPE_PARAMETER_BOUND:
   747             case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
   748                 out.writeByte(p.parameter_index);
   749                 out.writeByte(p.bound_index);
   750                 break;
   751              // wildcards
   752             case WILDCARD_BOUND:
   753             case WILDCARD_BOUND_GENERIC_OR_ARRAY:
   754                 write(p.wildcard_position, out);
   755                 break;
   756             // Class extends and implements clauses
   757             case CLASS_EXTENDS:
   758             case CLASS_EXTENDS_GENERIC_OR_ARRAY:
   759                 out.writeByte(p.type_index);
   760                 break;
   761             // throws
   762             case THROWS:
   763                 out.writeByte(p.type_index);
   764                 break;
   765             case CLASS_LITERAL:
   766                 out.writeShort(p.offset);
   767                 break;
   768             // method parameter: not specified
   769             case METHOD_PARAMETER_GENERIC_OR_ARRAY:
   770                 out.writeByte(p.parameter_index);
   771                 break;
   772             // method type argument: wasn't specified
   773             case METHOD_TYPE_ARGUMENT:
   774             case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
   775                 out.writeShort(p.offset);
   776                 out.writeByte(p.type_index);
   777                 break;
   778             // We don't need to worry abut these
   779             case METHOD_RETURN_GENERIC_OR_ARRAY:
   780             case FIELD_GENERIC_OR_ARRAY:
   781                 break;
   782             case UNKNOWN:
   783                 break;
   784             default:
   785                 throw new AssertionError("unknown type: " + p);
   786             }
   788             // Append location data for generics/arrays.
   789             if (p.type.hasLocation()) {
   790                 out.writeShort(p.location.size());
   791                 for (int i : p.location)
   792                     out.writeByte((byte)i);
   793             }
   794         }
   795     }
   796 }

mercurial