View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.classfile;
20  
21  import java.io.DataInput;
22  import java.io.DataOutputStream;
23  import java.io.IOException;
24  
25  import org.apache.bcel.Constants;
26  import org.apache.bcel.util.Args;
27  
28  /**
29   * This class represents a local variable within a method. It contains its scope, name, signature and index on the
30   * method's frame. It is used both to represent an element of the LocalVariableTable as well as an element of the
31   * LocalVariableTypeTable. The nomenclature used here may be a bit confusing; while the two items have the same layout
32   * in a class file, a LocalVariableTable attribute contains a descriptor_index, not a signatureIndex. The
33   * LocalVariableTypeTable attribute does have a signatureIndex.
34   *
35   * @see org.apache.bcel.classfile.Utility for more details on the difference.
36   * @see LocalVariableTable
37   * @see LocalVariableTypeTable
38   */
39  public final class LocalVariable implements Cloneable, Node, Constants {
40  
41      static final LocalVariable[] EMPTY_ARRAY = {};
42  
43      /** Range in which the variable is valid. */
44      private int startPc;
45  
46      private int length;
47  
48      /** Index in constant pool of variable name. */
49      private int nameIndex;
50  
51      /**
52       * Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature
53       */
54      private int signatureIndex;
55  
56      /*
57       * Variable is index'th local variable on this method's frame.
58       */
59      private int index;
60  
61      private ConstantPool constantPool;
62  
63      /** Never changes; used to match up with LocalVariableTypeTable entries. */
64      private final int origIndex;
65  
66      /**
67       * Constructs object from file stream.
68       *
69       * @param file Input stream.
70       * @throws IOException if an I/O error occurs.
71       */
72      LocalVariable(final DataInput file, final ConstantPool constantPool) throws IOException {
73          this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constantPool);
74      }
75  
76      /**
77       * Constructs a LocalVariable.
78       *
79       * @param startPc Range in which the variable is valid.
80       * @param length length of validity.
81       * @param nameIndex Index in constant pool of variable name.
82       * @param signatureIndex Index of variable's signature.
83       * @param index Variable is 'index'th local variable on the method's frame.
84       * @param constantPool Array of constants.
85       */
86      public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) {
87          this(startPc, length, nameIndex, signatureIndex, index, constantPool, index);
88      }
89  
90      /**
91       * Constructs a LocalVariable.
92       *
93       * @param startPc Range in which the variable is valid.
94       * @param length length of validity.
95       * @param nameIndex Index in constant pool of variable name.
96       * @param signatureIndex Index of variable's signature.
97       * @param index Variable is 'index'th local variable on the method's frame.
98       * @param constantPool Array of constants.
99       * @param origIndex Variable is 'index'th local variable on the method's frame prior to any changes.
100      */
101     public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool,
102         final int origIndex) {
103         this.startPc = Args.requireU2(startPc, "startPc");
104         this.length = Args.requireU2(length, "length");
105         this.nameIndex = Args.requireU2(nameIndex, "nameIndex");
106         this.signatureIndex = Args.requireU2(signatureIndex, "signatureIndex");
107         this.index = Args.requireU2(index, "index");
108         this.origIndex = Args.requireU2(origIndex, "origIndex");
109         this.constantPool = constantPool;
110     }
111 
112     /**
113      * Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for
114      * a physical copy.
115      *
116      * @param localVariable Another LocalVariable.
117      */
118     public LocalVariable(final LocalVariable localVariable) {
119         this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(),
120             localVariable.getConstantPool());
121     }
122 
123     /**
124      * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
125      * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
126      *
127      * @param v Visitor object.
128      */
129     @Override
130     public void accept(final Visitor v) {
131         v.visitLocalVariable(this);
132     }
133 
134     /**
135      * Creates a deep copy of this object.
136      *
137      * @return deep copy of this object.
138      */
139     public LocalVariable copy() {
140         try {
141             return (LocalVariable) clone();
142         } catch (final CloneNotSupportedException e) {
143             // TODO should this throw?
144         }
145         return null;
146     }
147 
148     /**
149      * Dumps local variable to file stream in binary format.
150      *
151      * @param dataOutputStream Output file stream.
152      * @throws IOException if an I/O error occurs.
153      * @see java.io.FilterOutputStream#out
154      */
155     public void dump(final DataOutputStream dataOutputStream) throws IOException {
156         dataOutputStream.writeShort(startPc);
157         dataOutputStream.writeShort(length);
158         dataOutputStream.writeShort(nameIndex);
159         dataOutputStream.writeShort(signatureIndex);
160         dataOutputStream.writeShort(index);
161     }
162 
163     /**
164      * Gets the constant pool used by this object.
165      *
166      * @return Constant pool used by this object.
167      */
168     public ConstantPool getConstantPool() {
169         return constantPool;
170     }
171 
172     /**
173      * Gets the index of register where variable is stored.
174      *
175      * @return index of register where variable is stored.
176      */
177     public int getIndex() {
178         return index;
179     }
180 
181     /**
182      * Gets the length of validity.
183      *
184      * @return Variable is valid within getStartPC() .. getStartPC()+getLength().
185      */
186     public int getLength() {
187         return length;
188     }
189 
190     /**
191      * Gets the variable name.
192      *
193      * @return Variable name.
194      */
195     public String getName() {
196         return constantPool.getConstantUtf8(nameIndex).getBytes();
197     }
198 
199     /**
200      * Gets the index in constant pool of variable name.
201      *
202      * @return Index in constant pool of variable name.
203      */
204     public int getNameIndex() {
205         return nameIndex;
206     }
207 
208     /**
209      * Gets the index of register where variable was originally stored.
210      *
211      * @return index of register where variable was originally stored.
212      */
213     public int getOrigIndex() {
214         return origIndex;
215     }
216 
217     /**
218      * Gets the signature.
219      *
220      * @return Signature.
221      */
222     public String getSignature() {
223         return constantPool.getConstantUtf8(signatureIndex).getBytes();
224     }
225 
226     /**
227      * Gets the index in constant pool of variable signature.
228      *
229      * @return Index in constant pool of variable signature.
230      */
231     public int getSignatureIndex() {
232         return signatureIndex;
233     }
234 
235     /**
236      * Gets the start of range where the variable is valid.
237      *
238      * @return Start of range where the variable is valid.
239      */
240     public int getStartPC() {
241         return startPc;
242     }
243 
244     /**
245      * Sets the constant pool to be used for this object.
246      *
247      * @param constantPool Constant pool to be used for this object.
248      */
249     public void setConstantPool(final ConstantPool constantPool) {
250         this.constantPool = constantPool;
251     }
252 
253     /**
254      * Sets the index in the local variable table of this variable.
255      *
256      * @param index the index in the local variable table of this variable.
257      */
258     public void setIndex(final int index) { // TODO unused
259         this.index = index;
260     }
261 
262     /**
263      * Sets the length of this local variable.
264      *
265      * @param length the length of this local variable.
266      */
267     public void setLength(final int length) {
268         this.length = length;
269     }
270 
271     /**
272      * Sets the index into the constant pool for the name of this variable.
273      *
274      * @param nameIndex the index into the constant pool for the name of this variable.
275      */
276     public void setNameIndex(final int nameIndex) { // TODO unused
277         this.nameIndex = nameIndex;
278     }
279 
280     /**
281      * Sets the index into the constant pool for the signature of this variable.
282      *
283      * @param signatureIndex the index into the constant pool for the signature of this variable.
284      */
285     public void setSignatureIndex(final int signatureIndex) { // TODO unused
286         this.signatureIndex = signatureIndex;
287     }
288 
289     /**
290      * Sets the range where the local variable is valid.
291      *
292      * @param startPc Specify range where the local variable is valid.
293      */
294     public void setStartPC(final int startPc) { // TODO unused
295         this.startPc = startPc;
296     }
297 
298     /**
299      * Gets the string representation.
300      *
301      * @return string representation.
302      */
303     @Override
304     public String toString() {
305         return toStringShared(false);
306     }
307 
308     /*
309      * Helper method shared with LocalVariableTypeTable
310      */
311     String toStringShared(final boolean typeTable) {
312         final String name = getName();
313         final String signature = Utility.signatureToString(getSignature(), false);
314         final String label = "LocalVariable" + (typeTable ? "Types" : "");
315         return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")";
316     }
317 }
318