View Javadoc
1   /**
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.bcel.classfile;
19  
20  import java.io.DataInput;
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  import java.util.Arrays;
24  import java.util.Iterator;
25  import java.util.stream.Stream;
26  
27  import org.apache.bcel.Const;
28  import org.apache.bcel.util.Args;
29  
30  // The new table is used when generic types are about...
31  
32  //LocalVariableTable_attribute {
33  //       u2 attribute_name_index;
34  //       u4 attribute_length;
35  //       u2 local_variable_table_length;
36  //       {  u2 start_pc;
37  //          u2 length;
38  //          u2 name_index;
39  //          u2 descriptor_index;
40  //          u2 index;
41  //       } local_variable_table[local_variable_table_length];
42  //     }
43  
44  //LocalVariableTypeTable_attribute {
45  //    u2 attribute_name_index;
46  //    u4 attribute_length;
47  //    u2 local_variable_type_table_length;
48  //    {
49  //      u2 start_pc;
50  //      u2 length;
51  //      u2 name_index;
52  //      u2 signature_index;
53  //      u2 index;
54  //    } localVariableTypeTable[local_variable_type_table_length];
55  //  }
56  // J5TODO: Needs some testing !
57  
58  /**
59   * @since 6.0
60   */
61  public class LocalVariableTypeTable extends Attribute implements Iterable<LocalVariable> {
62  
63      private LocalVariable[] localVariableTypeTable; // variables
64  
65      LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException {
66          this(nameIdx, len, (LocalVariable[]) null, cpool);
67  
68          final int localVariableTypeTableLength = input.readUnsignedShort();
69          localVariableTypeTable = new LocalVariable[localVariableTypeTableLength];
70  
71          for (int i = 0; i < localVariableTypeTableLength; i++) {
72              localVariableTypeTable[i] = new LocalVariable(input, cpool);
73          }
74      }
75  
76      public LocalVariableTypeTable(final int nameIndex, final int length, final LocalVariable[] localVariableTypeTable, final ConstantPool constantPool) {
77          super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, nameIndex, length, constantPool);
78          this.localVariableTypeTable = localVariableTypeTable != null ? localVariableTypeTable : LocalVariable.EMPTY_ARRAY;
79          Args.requireU2(this.localVariableTypeTable.length, "localVariableTypeTable.length");
80      }
81  
82      public LocalVariableTypeTable(final LocalVariableTypeTable c) {
83          this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool());
84      }
85  
86      @Override
87      public void accept(final Visitor v) {
88          v.visitLocalVariableTypeTable(this);
89      }
90  
91      /**
92       * @return deep copy of this attribute
93       */
94      @Override
95      public Attribute copy(final ConstantPool constantPool) {
96          final LocalVariableTypeTable c = (LocalVariableTypeTable) clone();
97  
98          c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length];
99          Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy());
100         c.setConstantPool(constantPool);
101         return c;
102     }
103 
104     @Override
105     public final void dump(final DataOutputStream file) throws IOException {
106         super.dump(file);
107         file.writeShort(localVariableTypeTable.length);
108         for (final LocalVariable variable : localVariableTypeTable) {
109             variable.dump(file);
110         }
111     }
112 
113     public final LocalVariable getLocalVariable(final int index) {
114         for (final LocalVariable variable : localVariableTypeTable) {
115             if (variable.getIndex() == index) {
116                 return variable;
117             }
118         }
119 
120         return null;
121     }
122 
123     public final LocalVariable[] getLocalVariableTypeTable() {
124         return localVariableTypeTable;
125     }
126 
127     public final int getTableLength() {
128         return localVariableTypeTable == null ? 0 : localVariableTypeTable.length;
129     }
130 
131     @Override
132     public Iterator<LocalVariable> iterator() {
133         return Stream.of(localVariableTypeTable).iterator();
134     }
135 
136     public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
137         this.localVariableTypeTable = localVariableTable;
138     }
139 
140     /**
141      * @return String representation.
142      */
143     @Override
144     public final String toString() {
145         final StringBuilder buf = new StringBuilder();
146 
147         for (int i = 0; i < localVariableTypeTable.length; i++) {
148             buf.append(localVariableTypeTable[i].toStringShared(true));
149 
150             if (i < localVariableTypeTable.length - 1) {
151                 buf.append('\n');
152             }
153         }
154 
155         return buf.toString();
156     }
157 }