1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.io.IOException;
6   import java.util.ArrayList;
7   
8   import static jminusminus.CLConstants.*;
9   
10  /**
11   * The abstract base class for the representation of attribute_info} structure. Classes
12   * representing individual attributes inherit this class. This file has representations for all
13   * attributes specified in JVM Spec Second Edition, including the ones that were added for JDK 1.5.
14   * <p>
15   * Attributes are used in the CLFile, CLFieldInfo, CLMethodInfo, and CLCodeAttribute structures
16   * of the class file. While there are many kinds of attributes, only some are mandatory; these
17   * include:
18   * <ul>
19   *   <li> InnerClasses_attribute (class attribute)</li>
20   *   <li> Synthetic_attribute (class, field, and method attribute)</li>
21   *   <li> Code_attribute (method attribute)</li>
22   *   <li> Exceptions_attribute (method attribute)</li>
23   * </ul>
24   * <p>
25   * CLEmitter implicitly adds the required attributes to the appropriate structure. The optional
26   * attributes have to be added explicitly using the CLEmitter methods addClassAttribute(),
27   * addFieldAttribute(), addMethodAttribute(), and addCodeAttribute().
28   */
29  abstract class CLAttributeInfo {
30      /**
31       * attribute_info.attribute_name_index item.
32       */
33      public int attributeNameIndex;
34  
35      /**
36       * attribute_info.attribute_length item.
37       */
38      public long attributeLength;
39  
40      /**
41       * Construct a CLAttributeInfo object.
42       *
43       * @param attributeNameIndex attribute_info.attribute_name_index item.
44       * @param attributeLength    attribute_info.attribute_length item.
45       */
46      protected CLAttributeInfo(int attributeNameIndex, long attributeLength) {
47          this.attributeNameIndex = attributeNameIndex;
48          this.attributeLength = attributeLength;
49      }
50  
51      /**
52       * Write the contents of this attribute to the specified output stream.
53       *
54       * @param out output stream.
55       * @throws IOException if an error occurs while writing.
56       */
57  
58      public void write(CLOutputStream out) throws IOException {
59          out.writeShort(attributeNameIndex);
60          out.writeInt((long) attributeLength);
61      }
62  }
63  
64  /**
65   * Representation of ConstantValue_attribute structure.
66   */
67  class CLConstantValueAttribute extends CLAttributeInfo {
68      /**
69       * ConstantValue_attribute.constantvalue_index item.
70       */
71      public int constantValueIndex;
72  
73      /**
74       * Construct a CLConstantValueAttribute object.
75       *
76       * @param attributeNameIndex ConstantValue_attribute.attribute_name_index item.
77       * @param attributeLength    ConstantValue_attribute.attribute_length item.
78       * @param constantValueIndex ConstantValue_attribute.constantvalue_index item.
79       */
80      public CLConstantValueAttribute(int attributeNameIndex, long attributeLength,
81                                      int constantValueIndex) {
82          super(attributeNameIndex, attributeLength);
83          this.constantValueIndex = constantValueIndex;
84      }
85  
86      /**
87       * {@inheritDoc}
88       */
89      public void write(CLOutputStream out) throws IOException {
90          super.write(out);
91          out.writeShort(constantValueIndex);
92      }
93  }
94  
95  /**
96   * Representation of exception_table entry structure.
97   */
98  class CLExceptionInfo {
99      /**
100      * exception_table_entry.start_pc item.
101      */
102     public int startPC;
103 
104     /**
105      * exception_table_entry.end_pc item.
106      */
107     public int endPC;
108 
109     /**
110      * exception_table_entry.handler_pc item.
111      */
112     public int handlerPC;
113 
114     /**
115      * exception_table_entry.catch_type item.
116      */
117     public int catchType;
118 
119     /**
120      * Construct a CLExceptionInfo object.
121      *
122      * @param startPC   exception_table_entry.start_pc item.
123      * @param endPC     exception_table_entry.end_pc item.
124      * @param handlerPC exception_table_entry.handler_pc item.
125      * @param catchType exception_table_entry.catch_type item.
126      */
127     public CLExceptionInfo(int startPC, int endPC, int handlerPC, int catchType) {
128         this.startPC = startPC;
129         this.endPC = endPC;
130         this.handlerPC = handlerPC;
131         this.catchType = catchType;
132     }
133 
134     /**
135      * Write the contents of this object to the specified output stream.
136      *
137      * @param out output stream.
138      * @throws IOException if an error occurs while writing.
139      */
140     public void write(CLOutputStream out) throws IOException {
141         out.writeShort(startPC);
142         out.writeShort(endPC);
143         out.writeShort(handlerPC);
144         out.writeShort(catchType);
145     }
146 }
147 
148 /**
149  * Representation of Code_attribute structure.
150  */
151 class CLCodeAttribute extends CLAttributeInfo {
152     /**
153      * Code_attribute.max_stack item.
154      */
155     public int maxStack;
156 
157     /**
158      * Code_attribute.max_locals item.
159      */
160     public int maxLocals;
161 
162     /**
163      * Code_attribute.code_length item.
164      */
165     public long codeLength;
166 
167     /**
168      * Code_attribute.code item.
169      */
170     public ArrayList<Integer> code;
171 
172     /**
173      * Code_attribute.exception_table_length item.
174      */
175     public int exceptionTableLength;
176 
177     /**
178      * Code_attribute.exception_table item.
179      */
180     public ArrayList<CLExceptionInfo> exceptionTable;
181 
182     /**
183      * Code_attribute.attributes_count item.
184      */
185     public int attributesCount;
186 
187     /**
188      * Code_attribute.attributes item.
189      */
190     public ArrayList<CLAttributeInfo> attributes;
191 
192     /**
193      * Construct a CLCodeAttribute object.
194      *
195      * @param attributeNameIndex   Code_attribute.attribute_name_index item.
196      * @param attributeLength      Code_attribute.attribute_length item.
197      * @param maxStack             Code_attribute.max_stack item.
198      * @param maxLocals            Code_attribute.max_locals item.
199      * @param codeLength           Code_attribute.code_length item.
200      * @param code                 Code_attribute.code item.
201      * @param exceptionTableLength Code_attribute.exception_table_length item.
202      * @param exceptionTable       Code_attribute.exception_table item.
203      * @param attributesCount      Code_attribute.attributes_count item.
204      * @param attributes           Code_attribute.attributes item.
205      */
206     public CLCodeAttribute(int attributeNameIndex, long attributeLength, int maxStack,
207                            int maxLocals, long codeLength, ArrayList<Integer> code,
208                            int exceptionTableLength, ArrayList<CLExceptionInfo> exceptionTable,
209                            int attributesCount, ArrayList<CLAttributeInfo> attributes) {
210         super(attributeNameIndex, attributeLength);
211         this.maxStack = maxStack;
212         this.maxLocals = maxLocals;
213         this.codeLength = codeLength;
214         this.code = code;
215         this.exceptionTableLength = exceptionTableLength;
216         this.exceptionTable = exceptionTable;
217         this.attributesCount = attributesCount;
218         this.attributes = attributes;
219     }
220 
221     /**
222      * {@inheritDoc}
223      */
224     public void write(CLOutputStream out) throws IOException {
225         super.write(out);
226         out.writeShort(maxStack);
227         out.writeShort(maxLocals);
228         out.writeInt(codeLength);
229         for (int info : code) {
230             out.writeByte(info);
231         }
232         out.writeShort(exceptionTableLength);
233         for (CLExceptionInfo info : exceptionTable) {
234             info.write(out);
235         }
236         out.writeShort(attributesCount);
237         for (CLAttributeInfo info : attributes) {
238             info.write(out);
239         }
240     }
241 }
242 
243 /**
244  * Representation of Exceptions_attribute structure.
245  */
246 class CLExceptionsAttribute extends CLAttributeInfo {
247     /**
248      * Exceptions_attribute.number_of_exceptions item.
249      */
250     public int numberOfExceptions;
251 
252     /**
253      * Exceptions_attribute.exception_index_table item.
254      */
255     public ArrayList<Integer> exceptionIndexTable;
256 
257     /**
258      * Construct a CLExceptionsAttribute object.
259      *
260      * @param attributeNameIndex  Exceptions_attribute.attribute_name_index item.
261      * @param attributeLength     Exceptions_attribute.attribute_length item.
262      * @param numberOfExceptions  Exceptions_attribute.number_of_exceptions item.
263      * @param exceptionIndexTable Exceptions_attribute.exception_index_table item.
264      */
265     public CLExceptionsAttribute(int attributeNameIndex, long attributeLength,
266                                  int numberOfExceptions, ArrayList<Integer> exceptionIndexTable) {
267         super(attributeNameIndex, attributeLength);
268         this.numberOfExceptions = numberOfExceptions;
269         this.exceptionIndexTable = exceptionIndexTable;
270     }
271 
272     /**
273      * {@inheritDoc}
274      */
275     public void write(CLOutputStream out) throws IOException {
276         super.write(out);
277         out.writeShort(numberOfExceptions);
278         for (int info : exceptionIndexTable) {
279             out.writeShort(info);
280         }
281     }
282 }
283 
284 /**
285  * Representation of classes table entry structure.
286  */
287 class CLInnerClassInfo {
288     /**
289      * classes_table_entry.inner_class_info_index item.
290      */
291     public int innerClassInfoIndex;
292 
293     /**
294      * classes_table_entry.outer_class_info_index item.
295      */
296     public int outerClassInfoIndex;
297 
298     /**
299      * classes_table_entry.inner_name_index item.
300      */
301     public int innerNameIndex;
302 
303     /**
304      * classes_table_entry.inner_class_access_flags item.
305      */
306     public int innerClassAccessFlags;
307 
308     /**
309      * Construct a CLInnerClassInfo object.
310      *
311      * @param innerClassInfoIndex   classes_table_entry.inner_class_info_index item.
312      * @param outerClassInfoIndex   classes_table_entry.outer_class_info_index item.
313      * @param innerNameIndex        classes_table_entry.inner_name_index item.
314      * @param innerClassAccessFlags classes_table_entry.inner_class_access_flags item.
315      */
316     public CLInnerClassInfo(int innerClassInfoIndex, int outerClassInfoIndex, int innerNameIndex,
317                             int innerClassAccessFlags) {
318         this.innerClassInfoIndex = innerClassInfoIndex;
319         this.outerClassInfoIndex = outerClassInfoIndex;
320         this.innerNameIndex = innerNameIndex;
321         this.innerClassAccessFlags = innerClassAccessFlags;
322     }
323 
324     /**
325      * Write the contents of this object to the specified output stream.
326      *
327      * @param out output stream.
328      * @throws IOException if an error occurs while writing.
329      */
330     public void write(CLOutputStream out) throws IOException {
331         out.writeShort(innerClassInfoIndex);
332         out.writeShort(outerClassInfoIndex);
333         out.writeShort(innerNameIndex);
334         out.writeShort(innerClassAccessFlags);
335     }
336 }
337 
338 /**
339  * Representation of InnerClasses_attribute structure.
340  * <p>
341  * Note that this is just to register the inner classes with its parent class, and does not
342  * create the classes, which can be done using CLEmitter.
343  */
344 class CLInnerClassesAttribute extends CLAttributeInfo {
345     /**
346      * InnerClasses_attribute.number_of_classes item.
347      */
348     public int numberOfClasses;
349 
350     /**
351      * InnerClasses_attribute.classes item.
352      */
353     public ArrayList<CLInnerClassInfo> classes;
354 
355     /**
356      * Construct a CLInnerClassesAttribute object.
357      *
358      * @param attributeNameIndex InnerClasses_attribute.attribute_name_index item.
359      * @param attributeLength    InnerClasses_attribute.attribute_length item.
360      * @param numberOfClasses    InnerClasses_attribute.number_of_classes item.
361      * @param classes            InnerClasses_attribute.classes item.
362      */
363     public CLInnerClassesAttribute(int attributeNameIndex, long attributeLength,
364                                    int numberOfClasses, ArrayList<CLInnerClassInfo> classes) {
365         super(attributeNameIndex, attributeLength);
366         this.numberOfClasses = numberOfClasses;
367         this.classes = classes;
368     }
369 
370     /**
371      * {@inheritDoc}
372      */
373     public void write(CLOutputStream out) throws IOException {
374         super.write(out);
375         out.writeShort(numberOfClasses);
376         for (CLInnerClassInfo info : classes) {
377             info.write(out);
378         }
379     }
380 }
381 
382 /**
383  * Representation of EnclosingMethod_attribute structure.
384  */
385 class CLEnclosingMethodAttribute extends CLAttributeInfo {
386     /**
387      * EnclosingMethod_attribute.class_index item.
388      */
389     public int classIndex;
390 
391     /**
392      * EnclosingMethod_attribute.method_index item.
393      */
394     public int methodIndex;
395 
396     /**
397      * Construct a CLEnclosingMethodAttribute object.
398      *
399      * @param attributeNameIndex EnclosingMethod_attribute.attribute_name_index item.
400      * @param attributeLength    EnclosingMethod_attribute.attribute_length item.
401      * @param classIndex         EnclosingMethod_attribute.class_index item.
402      * @param methodIndex        EnclosingMethod_attribute.method_index item.
403      */
404 
405     public CLEnclosingMethodAttribute(int attributeNameIndex, long attributeLength,
406                                       int classIndex, int methodIndex) {
407         super(attributeNameIndex, attributeLength);
408         this.classIndex = classIndex;
409         this.methodIndex = methodIndex;
410     }
411 
412     /**
413      * {@inheritDoc}
414      */
415     public void write(CLOutputStream out) throws IOException {
416         super.write(out);
417         out.writeShort(classIndex);
418         out.writeShort(methodIndex);
419     }
420 }
421 
422 /**
423  * Representation of Synthetic_attribute structure.
424  */
425 class CLSyntheticAttribute extends CLAttributeInfo {
426     /**
427      * Construct a CLSyntheticAttribute object.
428      *
429      * @param attributeNameIndex Synthetic_attribute.attribute_name_index item.
430      * @param attributeLength    Synthetic_attribute.attribute_length item.
431      */
432     public CLSyntheticAttribute(int attributeNameIndex, long attributeLength) {
433         super(attributeNameIndex, attributeLength);
434     }
435 
436     /**
437      * {@inheritDoc}
438      */
439     public void write(CLOutputStream out) throws IOException {
440         super.write(out);
441     }
442 }
443 
444 /**
445  * Representation of Signature_attribute structure.
446  */
447 class CLSignatureAttribute extends CLAttributeInfo {
448     /**
449      * Signature_attribute.signature_index item.
450      */
451     public int signatureIndex;
452 
453     /**
454      * Construct a CLSignatureAttribute object.
455      *
456      * @param attributeNameIndex Signature_attribute.attribute_name_index item.
457      * @param attributeLength    Signature_attribute.attribute_length item.
458      * @param signatureIndex     Signature_attribute.signature_index item.
459      */
460     public CLSignatureAttribute(int attributeNameIndex, long attributeLength, int signatureIndex) {
461         super(attributeNameIndex, attributeLength);
462         this.signatureIndex = signatureIndex;
463     }
464 
465     /**
466      * {@inheritDoc}
467      */
468     public void write(CLOutputStream out) throws IOException {
469         super.write(out);
470         out.writeShort(signatureIndex);
471     }
472 }
473 
474 /**
475  * Representation of SourceFile_attribute structure.
476  */
477 class CLSourceFileAttribute extends CLAttributeInfo {
478     /**
479      * SourceFile_attribute.sourcefile_index item.
480      */
481     public int sourceFileIndex;
482 
483     /**
484      * Construct a CLSourceFileAttribute object.
485      *
486      * @param attributeNameIndex SourceFile_attribute.attribute_name_index item.
487      * @param attributeLength    SourceFile_attribute.attribute_length item.
488      * @param sourceFileIndex    SourceFile_attribute.sourcefile_index item.
489      */
490     public CLSourceFileAttribute(int attributeNameIndex, long attributeLength,
491                                  int sourceFileIndex) {
492         super(attributeNameIndex, attributeLength);
493         this.sourceFileIndex = sourceFileIndex;
494     }
495 
496     /**
497      * {@inheritDoc}
498      */
499     public void write(CLOutputStream out) throws IOException {
500         super.write(out);
501         out.writeShort(sourceFileIndex);
502     }
503 }
504 
505 /**
506  * Representation of SourceDebugExtension_attribute structure.
507  */
508 class CLSourceDebugExtensionAttribute extends CLAttributeInfo {
509     /**
510      * SoureDebugExtension.debug_extension item.
511      */
512     public byte[] debugExtension;
513 
514     /**
515      * Construct a CLSourceDebugExtensionAttribute object.
516      *
517      * @param attributeNameIndex SourceDebugExtension_attribute.attribute_name_index item.
518      * @param attributeLength    SourceDebugExtension_attribute.attribute_length item.
519      * @param debugExtension     SourceDebugExtension_attribute.debug_extension item.
520      */
521     public CLSourceDebugExtensionAttribute(int attributeNameIndex, long attributeLength,
522                                            byte[] debugExtension) {
523         super(attributeNameIndex, attributeLength);
524         this.debugExtension = debugExtension;
525     }
526 
527     /**
528      * {@inheritDoc}
529      */
530     public void write(CLOutputStream out) throws IOException {
531         super.write(out);
532         for (byte info : debugExtension) {
533             out.writeByte(info);
534         }
535     }
536 }
537 
538 /**
539  * Representation of line_number_table entry structure.
540  */
541 class CLLineNumberInfo {
542     /**
543      * line_number_table_entry.start_pc item.
544      */
545     public int startPC;
546 
547     /**
548      * line_number_table_entry.line_number item.
549      */
550     public int lineNumber;
551 
552     /**
553      * Construct a CLLineNumberInfo object.
554      *
555      * @param startPC    line_number_table_entry.start_pc item.
556      * @param lineNumber line_number_table_entry.line_number item.
557      */
558     public CLLineNumberInfo(int startPC, int lineNumber) {
559         this.startPC = startPC;
560         this.lineNumber = lineNumber;
561     }
562 
563     /**
564      * Write the contents of this object to the specified output stream.
565      *
566      * @param out output stream.
567      * @throws IOException if an error occurs while writing.
568      */
569     public void write(CLOutputStream out) throws IOException {
570         out.writeShort(startPC);
571         out.writeShort(lineNumber);
572     }
573 
574     /**
575      * Return true if this LineNumber_info object is the same as other, and false otherwise.
576      *
577      * @param other the reference LineNumber_info object with which to compare.
578      * @return true if this LineNumber_info object is the same as other, and false otherwise.
579      */
580     public boolean equals(Object other) {
581         if (other instanceof CLLineNumberInfo) {
582             CLLineNumberInfo c = (CLLineNumberInfo) other;
583             if (c.lineNumber == lineNumber) {
584                 return true;
585             }
586         }
587         return false;
588     }
589 }
590 
591 /**
592  * Representation of LineNumberTable_attribute structure.
593  */
594 class CLLineNumberTableAttribute extends CLAttributeInfo {
595     /**
596      * LineNumberTable_attribute.line_number_table_length item.
597      */
598     public int lineNumberTableLength;
599 
600     /**
601      * LineNumberTable_attribute.line_number_table item.
602      */
603     public ArrayList<CLLineNumberInfo> lineNumberTable;
604 
605     /**
606      * Construct a CLLineNumberTableAttribute object.
607      *
608      * @param attributeNameIndex    LineNumberTable_attribute.attribute_name_index item.
609      * @param attributeLength       LineNumberTable_attribute.attribute_length item.
610      * @param lineNumberTableLength LineNumberTable_attribute.line_number_table_length item.
611      * @param lineNumberTable       LineNumberTable_attribute.line_number_table item.
612      */
613     public CLLineNumberTableAttribute(int attributeNameIndex, long attributeLength,
614                                       int lineNumberTableLength,
615                                       ArrayList<CLLineNumberInfo> lineNumberTable) {
616         super(attributeNameIndex, attributeLength);
617         this.lineNumberTableLength = lineNumberTableLength;
618         this.lineNumberTable = lineNumberTable;
619     }
620 
621     /**
622      * {@inheritDoc}
623      */
624     public void write(CLOutputStream out) throws IOException {
625         super.write(out);
626         out.writeShort(lineNumberTableLength);
627         for (CLLineNumberInfo info : lineNumberTable) {
628             info.write(out);
629         }
630     }
631 }
632 
633 /**
634  * Representation of local_variable_table entry structure.
635  */
636 class CLLocalVariableInfo {
637     /**
638      * local_variable_table_entry.start_pc item.
639      */
640     public int startPC;
641 
642     /**
643      * local_variable_table_entry.length item.
644      */
645     public int length;
646 
647     /**
648      * local_variable_table_entry.name_index item.
649      */
650     public int nameIndex;
651 
652     /**
653      * local_variable_table_entry.descriptor_index item.
654      */
655     public int descriptorIndex;
656 
657     /**
658      * local_variable_table_entry.index item.
659      */
660     public int index;
661 
662     /**
663      * Construct a CLLocalVariableInfo object.
664      *
665      * @param startPC         local_variable_table_entry.start_pc item.
666      * @param length          local_variable_table_entry.length item.
667      * @param nameIndex       local_variable_table_entry.name_index item.
668      * @param descriptorIndex local_variable_table_entry.descriptor_index item.
669      * @param index           local_variable_table_entry.index item.
670      */
671     public CLLocalVariableInfo(int startPC, int length, int nameIndex, int descriptorIndex,
672                                int index) {
673         this.startPC = startPC;
674         this.length = length;
675         this.nameIndex = nameIndex;
676         this.descriptorIndex = descriptorIndex;
677         this.index = index;
678     }
679 
680     /**
681      * Write the contents of this object to the specified output stream.
682      *
683      * @param out output stream.
684      * @throws IOException if an error occurs while writing.
685      */
686     public void write(CLOutputStream out) throws IOException {
687         out.writeShort(startPC);
688         out.writeShort(length);
689         out.writeShort(nameIndex);
690         out.writeShort(descriptorIndex);
691         out.writeShort(index);
692     }
693 }
694 
695 /**
696  * Representation of LocalVariableTable_attribute structure.
697  */
698 class CLLocalVariableTableAttribute extends CLAttributeInfo {
699     /**
700      * LocalVariableTable_attribute.local_variable_table_length item.
701      */
702     public int localVariableTableLength;
703 
704     /**
705      * LocalVariableTable_attribute.local_variable_table item.
706      */
707     public ArrayList<CLLocalVariableInfo> localVariableTable;
708 
709     /**
710      * Construct a CLLocalVariableTableAttribute object.
711      *
712      * @param attributeNameIndex       LocalVariableTable_attribute.attribute_name_index item.
713      * @param attributeLength          LocalVariableTable_attribute.attribute_length item.
714      * @param localVariableTableLength LocalVariableTable_attribute.local_variable_table_length item.
715      * @param localVariableTable       LocalVariableTable_attribute.local_variable_table item.
716      */
717     public CLLocalVariableTableAttribute(int attributeNameIndex, long attributeLength,
718                                          int localVariableTableLength,
719                                          ArrayList<CLLocalVariableInfo> localVariableTable) {
720         super(attributeNameIndex, attributeLength);
721         this.localVariableTableLength = localVariableTableLength;
722         this.localVariableTable = localVariableTable;
723     }
724 
725     /**
726      * {@inheritDoc}
727      */
728     public void write(CLOutputStream out) throws IOException {
729         super.write(out);
730         out.writeShort(localVariableTableLength);
731         for (CLLocalVariableInfo info : localVariableTable) {
732             info.write(out);
733         }
734     }
735 }
736 
737 /**
738  * Representation of local_variable_type_table entry structure.
739  */
740 class CLLocalVariableTypeInfo {
741     /**
742      * local_variable_type_table_entry.start_pc item.
743      */
744     public int startPC;
745 
746     /**
747      * local_variable_type_table_entry.length item.
748      */
749     public int length;
750 
751     /**
752      * local_variable_type_table_entry.name_index item.
753      */
754     public int nameIndex;
755 
756     /**
757      * local_variable_type_table_entry.descriptor_index item.
758      */
759     public int signatureIndex;
760 
761     /**
762      * local_variable_type_table_entry.index item.
763      */
764     public int index;
765 
766     /**
767      * Construct a CLLocalVariableTypeInfo object.
768      *
769      * @param startPC        local_variable_type_table_entry.start_pc item.
770      * @param length         local_variable_type_table_entry.length item.
771      * @param nameIndex      local_variable_type_table_entry.name_index item.
772      * @param signatureIndex local_variable_type_table_entry.signature_index item.
773      * @param index          local_variable_type_table_entry.index item.
774      */
775 
776     public CLLocalVariableTypeInfo(int startPC, int length, int nameIndex, int signatureIndex,
777                                    int index) {
778         this.startPC = startPC;
779         this.length = length;
780         this.nameIndex = nameIndex;
781         this.signatureIndex = signatureIndex;
782         this.index = index;
783     }
784 
785     /**
786      * Write the contents of this object to the specified output stream.
787      *
788      * @param out output stream.
789      * @throws IOException if an error occurs while writing.
790      */
791     public void write(CLOutputStream out) throws IOException {
792         out.writeShort(startPC);
793         out.writeShort(length);
794         out.writeShort(nameIndex);
795         out.writeShort(signatureIndex);
796         out.writeShort(index);
797     }
798 }
799 
800 /**
801  * Representation of LocalVariableTypeTable_attribute structure.
802  */
803 class CLLocalVariableTypeTableAttribute extends CLAttributeInfo {
804     /**
805      * LocalVariableTypeTable_attribute. local_variable_type_table_length item.
806      */
807     public int localVariableTypeTableLength;
808 
809     /**
810      * LocalVariableTypeTable_attribute.local_variable_type_table item.
811      */
812     public ArrayList<CLLocalVariableTypeInfo> localVariableTypeTable;
813 
814     /**
815      * Construct a CLLocalVariableTypeTableAttribute object.
816      *
817      * @param attributeNameIndex           LocalVariableTypeTable_attribute.attribute_name_index
818      *                                     item.
819      * @param attributeLength              LocalVariableTypeTable_attribute.attribute_length item.
820      * @param localVariableTypeTableLength LocalVariableTypeTable_attribute.
821      *                                     local_variable_type_table_length item.
822      * @param localVariableTypeTable       LocalVariableTypeTable_attribute.local_variable_type_table
823      *                                     item.
824      */
825     public CLLocalVariableTypeTableAttribute(int attributeNameIndex, long attributeLength,
826                                              int localVariableTypeTableLength,
827                                              ArrayList<CLLocalVariableTypeInfo>
828                                                      localVariableTypeTable) {
829         super(attributeNameIndex, attributeLength);
830         this.localVariableTypeTableLength = localVariableTypeTableLength;
831         this.localVariableTypeTable = localVariableTypeTable;
832     }
833 
834     /**
835      * {@inheritDoc}
836      */
837     public void write(CLOutputStream out) throws IOException {
838         super.write(out);
839         out.writeShort(localVariableTypeTableLength);
840         for (CLLocalVariableTypeInfo info : localVariableTypeTable) {
841             info.write(out);
842         }
843     }
844 }
845 
846 /**
847  * Representation of Deprecated_attribute structure.
848  */
849 class CLDeprecatedAttribute extends CLAttributeInfo {
850     /**
851      * Construct a CLDeprecatedAttribute object.
852      *
853      * @param attributeNameIndex Deprecated_attribute.attribute_name_index item.
854      * @param attributeLength    Deprecated_attribute.attribute_length item.
855      */
856     public CLDeprecatedAttribute(int attributeNameIndex, long attributeLength) {
857         super(attributeNameIndex, attributeLength);
858     }
859 
860     /**
861      * {@inheritDoc}
862      */
863     public void write(CLOutputStream out) throws IOException {
864         super.write(out);
865     }
866 }
867 
868 /**
869  * Representation of annotation structure.
870  */
871 class CLAnnotation {
872     /**
873      * annotation.type_index item.
874      */
875     public int typeIndex;
876 
877     /**
878      * annotation.num_element_value_pairs item.
879      */
880     public int numElementValuePairs;
881 
882     /**
883      * annotation.element_value_pairs item.
884      */
885     public ArrayList<CLElementValuePair> elementValuePairs;
886 
887     /**
888      * Construct a CLAnnotation object.
889      *
890      * @param typeIndex            annotation.type_index item.
891      * @param numElementValuePairs annotation.num_element_value_pairs item.
892      * @param elementValuePairs    annotation.element_value_pairs item.
893      */
894     public CLAnnotation(int typeIndex, int numElementValuePairs,
895                         ArrayList<CLElementValuePair> elementValuePairs) {
896         this.typeIndex = typeIndex;
897         this.numElementValuePairs = numElementValuePairs;
898         this.elementValuePairs = elementValuePairs;
899     }
900 
901     /**
902      * Write the contents of this object to the specified output stream.
903      *
904      * @param out output stream.
905      * @throws IOException if an error occurs while writing.
906      */
907     public void write(CLOutputStream out) throws IOException {
908         out.writeShort(typeIndex);
909         out.writeShort(numElementValuePairs);
910         for (CLElementValuePair info : elementValuePairs) {
911             info.write(out);
912         }
913     }
914 }
915 
916 /**
917  * Representation of element_value union.
918  */
919 class CLElementValue {
920     /**
921      * element_value.tag item.
922      */
923     public short tag;
924 
925     /**
926      * element_value.const_value_index item.
927      */
928     public int constValueIndex;
929 
930     /**
931      * element_value.enum_const_value.type_name_index item.
932      */
933     public int typeNameIndex;
934 
935     /**
936      * element_value.enum_const_value.const_name_index item.
937      */
938     public int constNameIndex;
939 
940     /**
941      * element_value.class_info_index item.
942      */
943     public int classInfoIndex;
944 
945     /**
946      * element_value.annotation_value item.
947      */
948     public CLAnnotation annotationValue;
949 
950     /**
951      * element_value.array_value.numValues item.
952      */
953     public int numValues;
954 
955     /**
956      * element_value.array_value.values item.
957      */
958     public ArrayList<CLElementValue> values;
959 
960     /**
961      * Construct a CLElementValue object.
962      *
963      * @param tag             element_value.tag item.
964      * @param constValueIndex element_value.const_value_index item.
965      */
966     public CLElementValue(short tag, int constValueIndex) {
967         this.tag = tag;
968         this.constValueIndex = constValueIndex;
969     }
970 
971     /**
972      * Construct a CLElementValue object.
973      *
974      * @param typeNameIndex  element_value.type_name_index item.
975      * @param constNameIndex element_value.const_name_index item.
976      */
977     public CLElementValue(int typeNameIndex, int constNameIndex) {
978         this.tag = ELT_e;
979         this.typeNameIndex = typeNameIndex;
980         this.constNameIndex = constNameIndex;
981     }
982 
983     /**
984      * Construct a CLElementValue object.
985      *
986      * @param classInfoIndex element_value.class_info_index item.
987      */
988     public CLElementValue(int classInfoIndex) {
989         this.tag = ELT_c;
990         this.classInfoIndex = classInfoIndex;
991     }
992 
993     /**
994      * Construct a CLElementValue object.
995      *
996      * @param annotationValue element_value.annotation_value item.
997      */
998     public CLElementValue(CLAnnotation annotationValue) {
999         this.tag = ELT_ANNOTATION;
1000        this.annotationValue = annotationValue;
1001    }
1002
1003    /**
1004     * Construct a CLElementValue object.
1005     *
1006     * @param numValues element_value.num_values.
1007     * @param values    element_value.values.
1008     */
1009    public CLElementValue(int numValues, ArrayList<CLElementValue> values) {
1010        this.tag = ELT_ARRAY;
1011        this.numValues = numValues;
1012        this.values = values;
1013    }
1014
1015    /**
1016     * Write the contents of this object to the specified output stream.
1017     *
1018     * @param out output stream.
1019     * @throws IOException if an error occurs while writing.
1020     */
1021    public void write(CLOutputStream out) throws IOException {
1022        out.writeByte(tag);
1023        switch (tag) {
1024            case ELT_B:
1025            case ELT_C:
1026            case ELT_D:
1027            case ELT_F:
1028            case ELT_I:
1029            case ELT_J:
1030            case ELT_S:
1031            case ELT_Z:
1032            case ELT_s:
1033                out.writeInt(constValueIndex);
1034                break;
1035            case ELT_e:
1036                out.writeInt(typeNameIndex);
1037                out.writeInt(constNameIndex);
1038                break;
1039            case ELT_c:
1040                out.writeInt(classInfoIndex);
1041                break;
1042            case ELT_ANNOTATION:
1043                annotationValue.write(out);
1044                break;
1045            case ELT_ARRAY:
1046                out.writeInt(numValues);
1047                for (CLElementValue info : values) {
1048                    info.write(out);
1049                }
1050        }
1051    }
1052}
1053
1054/**
1055 * Representation of the element_value_pairs table entry.
1056 */
1057class CLElementValuePair {
1058    /**
1059     * element_value_pairs_table_entry.element_name_index item.
1060     */
1061    public int elementNameIndex;
1062
1063    /**
1064     * element_value_pairs_table_entry.value item.
1065     */
1066    public CLElementValue value;
1067
1068    /**
1069     * Construct a CLElementValuePair object.
1070     *
1071     * @param elementNameIndex element_value_pairs_table_entry.element_name_index item.
1072     * @param value            element_value_pairs_table_entry.value item.
1073     */
1074    public CLElementValuePair(int elementNameIndex, CLElementValue value) {
1075        this.elementNameIndex = elementNameIndex;
1076        this.value = value;
1077    }
1078
1079    /**
1080     * Write the contents of this object to the specified output stream.
1081     *
1082     * @param out output stream.
1083     * @throws IOException if an error occurs while writing.
1084     */
1085    public void write(CLOutputStream out) throws IOException {
1086        out.writeShort(elementNameIndex);
1087        value.write(out);
1088    }
1089}
1090
1091/**
1092 * Representation of RuntimeVisibleAnnotations_attribute structure.
1093 */
1094class CLRuntimeVisibleAnnotationsAttribute extends CLAttributeInfo {
1095    /**
1096     * RuntimeVisibleAnnotations_attribute.num_annotations item.
1097     */
1098    public int numAnnotations;
1099
1100    /**
1101     * RuntimeVisibleAnnotations_attribute.annotations item.
1102     */
1103    public ArrayList<CLAnnotation> annotations;
1104
1105    /**
1106     * Construct a CLRuntimeVisibleAnnotationsAttribute object.
1107     *
1108     * @param attributeNameIndex RuntimeVisibleAnnotations_attribute.attribute_name_index item.
1109     * @param attributeLength    RuntimeVisibleAnnotations_attribute.attribute_length item.
1110     * @param numAnnotations     RuntimeVisibleAnnotations_attribute.num_annotations item.
1111     * @param annotations        RuntimeVisibleAnnotations_attribute.annotations item.
1112     */
1113    public CLRuntimeVisibleAnnotationsAttribute(int attributeNameIndex, long attributeLength,
1114                                                int numAnnotations,
1115                                                ArrayList<CLAnnotation> annotations) {
1116        super(attributeNameIndex, attributeLength);
1117        this.numAnnotations = numAnnotations;
1118        this.annotations = annotations;
1119    }
1120
1121    /**
1122     * {@inheritDoc}
1123     */
1124    public void write(CLOutputStream out) throws IOException {
1125        super.write(out);
1126        out.writeShort(numAnnotations);
1127        for (CLAnnotation info : annotations) {
1128            info.write(out);
1129        }
1130    }
1131}
1132
1133/**
1134 * Representation of RuntimeInvisibleAnnotations_attribute structure.
1135 */
1136class CLRuntimeInvisibleAnnotationsAttribute extends CLAttributeInfo {
1137    /**
1138     * RuntimeInvisibleAnnotations_attribute.num_annotations item.
1139     */
1140    public int numAnnotations;
1141
1142    /**
1143     * RuntimeInvisibleAnnotations_attribute.annotations item.
1144     */
1145    public ArrayList<CLAnnotation> annotations;
1146
1147    /**
1148     * Construct a CLRuntimeInvisibleAnnotationsAttribute object.
1149     *
1150     * @param attributeNameIndex RuntimeInvisibleAnnotations_attribute.attribute_name_index
1151     *                           item.
1152     * @param attributeLength    RuntimeInvisibleAnnotations_attribute.attribute_length item.
1153     * @param numAnnotations     RuntimeVisibleAnnotations_attribute.num_annotations item.
1154     * @param annotations        RuntimeInvisibleAnnotations_attribute.annotations item.
1155     */
1156    public CLRuntimeInvisibleAnnotationsAttribute(int attributeNameIndex, long attributeLength,
1157                                                  int numAnnotations,
1158                                                  ArrayList<CLAnnotation> annotations) {
1159        super(attributeNameIndex, attributeLength);
1160        this.numAnnotations = numAnnotations;
1161        this.annotations = annotations;
1162    }
1163
1164    /**
1165     * {@inheritDoc}
1166     */
1167    public void write(CLOutputStream out) throws IOException {
1168        super.write(out);
1169        out.writeShort(numAnnotations);
1170        for (CLAnnotation info : annotations) {
1171            info.write(out);
1172        }
1173    }
1174}
1175
1176/**
1177 * Representation of parameter_annotations_table entry structure.
1178 */
1179class CLParameterAnnotationInfo {
1180    /**
1181     * parameter_annotations_table_entry.num_annotations item.
1182     */
1183    public int numAnnotations;
1184
1185    /**
1186     * parameter_annotations_table_entry.annotations item.
1187     */
1188    public ArrayList<CLAnnotation> annotations;
1189
1190    /**
1191     * Construct a ParameterAnnotationInfo object.
1192     *
1193     * @param numAnnotations parameter_annotations_table_entry.num_annotations item.
1194     * @param annotations    parameter_annotations_table_entry.annotations item.
1195     */
1196    public CLParameterAnnotationInfo(int numAnnotations, ArrayList<CLAnnotation> annotations) {
1197        this.numAnnotations = numAnnotations;
1198        this.annotations = annotations;
1199    }
1200
1201    /**
1202     * Write the contents of this object to the specified output stream.
1203     *
1204     * @param out output stream.
1205     * @throws IOException if an error occurs while writing.
1206     */
1207    public void write(CLOutputStream out) throws IOException {
1208        out.writeShort(numAnnotations);
1209        for (CLAnnotation info : annotations) {
1210            info.write(out);
1211        }
1212    }
1213}
1214
1215/**
1216 * Representation of RuntimeVisibleParameterAnnotations_attribute structure.
1217 */
1218class CLRuntimeVisibleParameterAnnotationsAttribute extends CLAttributeInfo {
1219    /**
1220     * RuntimeVisibleParameterAnnotations_attribute.num_parameters item.
1221     */
1222    public short numParameters;
1223
1224    /**
1225     * RuntimeVisibleParameterAnnotations_attribute. parameter_annotations item.
1226     */
1227    public ArrayList<CLParameterAnnotationInfo> parameterAnnotations;
1228
1229    /**
1230     * Construct a CLRuntimeVisibleParameterAnnotationsAttribute object.
1231     *
1232     * @param attributeNameIndex   RuntimeVisibleParameterAnnotations_attribute.
1233     *                             attribute_name_index item.
1234     * @param attributeLength      RuntimeVisibleParameterAnnotations_attribute.attribute_length
1235     *                             item.
1236     * @param numParameters        RuntimeVisibleParameterAnnotations_attribute.num_parameters
1237     *                             item.
1238     * @param parameterAnnotations RuntimeVisibleParameterAnnotations_attribute.
1239     *                             parameter_annotations item.
1240     */
1241    public CLRuntimeVisibleParameterAnnotationsAttribute(int attributeNameIndex,
1242                                                         long attributeLength, short numParameters,
1243                                                         ArrayList<CLParameterAnnotationInfo>
1244                                                                 parameterAnnotations) {
1245        super(attributeNameIndex, attributeLength);
1246        this.numParameters = numParameters;
1247        this.parameterAnnotations = parameterAnnotations;
1248    }
1249
1250    /**
1251     * {@inheritDoc}
1252     */
1253    public void write(CLOutputStream out) throws IOException {
1254        super.write(out);
1255        out.writeByte(numParameters);
1256        for (CLParameterAnnotationInfo info : parameterAnnotations) {
1257            info.write(out);
1258        }
1259    }
1260}
1261
1262/**
1263 * Representation of RuntimeInvisibleParameterAnnotations_attribute structure.
1264 */
1265class CLRuntimeInvisibleParameterAnnotationsAttribute extends CLAttributeInfo {
1266    /**
1267     * RuntimeInvisibleParameterAnnotations_attribute.num_parameters item.
1268     */
1269    public short numParameters;
1270
1271    /**
1272     * RuntimeInvisibleParameterAnnotations_attribute. parameter_annotations
1273     * item.
1274     */
1275    public ArrayList<CLParameterAnnotationInfo> parameterAnnotations;
1276
1277    /**
1278     * Construct a CLRuntimeInvisibleParameterAnnotationsAttribute object.
1279     *
1280     * @param attributeNameIndex   RuntimeInvisibleParameterAnnotations_attribute.
1281     *                             attribute_name_index item.
1282     * @param attributeLength      RuntimeInvisibleParameterAnnotations_attribute.
1283     *                             attribute_length item.
1284     * @param numParameters        RuntimeInvisibleParameterAnnotations_attribute.num_parameters
1285     *                             item.
1286     * @param parameterAnnotations RuntimeInvisibleParameterAnnotations_attribute.
1287     *                             parameter_annotations item.
1288     */
1289    public CLRuntimeInvisibleParameterAnnotationsAttribute(int attributeNameIndex,
1290                                                           long attributeLength,
1291                                                           short numParameters,
1292                                                           ArrayList<CLParameterAnnotationInfo>
1293                                                                   parameterAnnotations) {
1294        super(attributeNameIndex, attributeLength);
1295        this.numParameters = numParameters;
1296        this.parameterAnnotations = parameterAnnotations;
1297    }
1298
1299    /**
1300     * {@inheritDoc}
1301     */
1302    public void write(CLOutputStream out) throws IOException {
1303        super.write(out);
1304        out.writeByte(numParameters);
1305        for (CLParameterAnnotationInfo info : parameterAnnotations) {
1306            info.write(out);
1307        }
1308    }
1309}
1310
1311/**
1312 * Representation of AnnotationDefault_attribute structure.
1313 */
1314class CLAnnotationDefaultAttribute extends CLAttributeInfo {
1315    /**
1316     * AnnotationDefault_attribute.defaultValue item.
1317     */
1318    public CLElementValue defaultValue;
1319
1320    /**
1321     * Construct a CLAnnotationDefaultAttribute object.
1322     *
1323     * @param attributeNameIndex AnnotationDefault_attribute.attribute_name_index item.
1324     * @param attributeLength    AnnotationDefault_attribute.attribute_length item.
1325     * @param defaultValue       AnnotationDefault_attribute.defaultValue item.
1326     */
1327    public CLAnnotationDefaultAttribute(int attributeNameIndex, long attributeLength,
1328                                        CLElementValue defaultValue) {
1329        super(attributeNameIndex, attributeLength);
1330        this.defaultValue = defaultValue;
1331    }
1332
1333    /**
1334     * {@inheritDoc}
1335     */
1336    public void write(CLOutputStream out) throws IOException {
1337        super.write(out);
1338        defaultValue.write(out);
1339    }
1340}
1341