001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.classfile; 018 019import java.io.DataInput; 020import java.io.DataOutputStream; 021import java.io.IOException; 022 023import org.apache.bcel.Constants; 024import org.apache.bcel.util.Args; 025 026/** 027 * This class represents a local variable within a method. It contains its scope, name, signature and index on the 028 * method's frame. It is used both to represent an element of the LocalVariableTable as well as an element of the 029 * LocalVariableTypeTable. The nomenclature used here may be a bit confusing; while the two items have the same layout 030 * in a class file, a LocalVariableTable attribute contains a descriptor_index, not a signatureIndex. The 031 * LocalVariableTypeTable attribute does have a signatureIndex. 032 * 033 * @see org.apache.bcel.classfile.Utility for more details on the difference. 034 * 035 * @see LocalVariableTable 036 * @see LocalVariableTypeTable 037 */ 038public final class LocalVariable implements Cloneable, Node, Constants { 039 040 static final LocalVariable[] EMPTY_ARRAY = {}; 041 042 /** Range in which the variable is valid. */ 043 private int startPc; 044 045 private int length; 046 047 /** Index in constant pool of variable name. */ 048 private int nameIndex; 049 050 /** 051 * Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature 052 */ 053 private int signatureIndex; 054 055 /* 056 * Variable is index'th local variable on this method's frame. 057 */ 058 private int index; 059 060 private ConstantPool constantPool; 061 062 /** Never changes; used to match up with LocalVariableTypeTable entries. */ 063 private final int origIndex; 064 065 /** 066 * Constructs object from file stream. 067 * 068 * @param file Input stream 069 * @throws IOException if an I/O error occurs. 070 */ 071 LocalVariable(final DataInput file, final ConstantPool constantPool) throws IOException { 072 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constantPool); 073 } 074 075 /** 076 * @param startPc Range in which the variable 077 * @param length ... is valid 078 * @param nameIndex Index in constant pool of variable name 079 * @param signatureIndex Index of variable's signature 080 * @param index Variable is 'index'th local variable on the method's frame 081 * @param constantPool Array of constants 082 */ 083 public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) { 084 this(startPc, length, nameIndex, signatureIndex, index, constantPool, index); 085 } 086 087 /** 088 * @param startPc Range in which the variable 089 * @param length ... is valid 090 * @param nameIndex Index in constant pool of variable name 091 * @param signatureIndex Index of variable's signature 092 * @param index Variable is 'index'th local variable on the method's frame 093 * @param constantPool Array of constants 094 * @param origIndex Variable is 'index'th local variable on the method's frame prior to any changes 095 */ 096 public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool, 097 final int origIndex) { 098 this.startPc = Args.requireU2(startPc, "startPc"); 099 this.length = Args.requireU2(length, "length"); 100 this.nameIndex = Args.requireU2(nameIndex, "nameIndex"); 101 this.signatureIndex = Args.requireU2(signatureIndex, "signatureIndex"); 102 this.index = Args.requireU2(index, "index"); 103 this.origIndex = Args.requireU2(origIndex, "origIndex"); 104 this.constantPool = constantPool; 105 } 106 107 /** 108 * Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for 109 * a physical copy. 110 * 111 * @param localVariable Another LocalVariable. 112 */ 113 public LocalVariable(final LocalVariable localVariable) { 114 this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(), 115 localVariable.getConstantPool()); 116 } 117 118 /** 119 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 120 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 121 * 122 * @param v Visitor object 123 */ 124 @Override 125 public void accept(final Visitor v) { 126 v.visitLocalVariable(this); 127 } 128 129 /** 130 * @return deep copy of this object 131 */ 132 public LocalVariable copy() { 133 try { 134 return (LocalVariable) clone(); 135 } catch (final CloneNotSupportedException e) { 136 // TODO should this throw? 137 } 138 return null; 139 } 140 141 /** 142 * Dumps local variable to file stream in binary format. 143 * 144 * @param dataOutputStream Output file stream 145 * @throws IOException if an I/O error occurs. 146 * @see java.io.FilterOutputStream#out 147 */ 148 public void dump(final DataOutputStream dataOutputStream) throws IOException { 149 dataOutputStream.writeShort(startPc); 150 dataOutputStream.writeShort(length); 151 dataOutputStream.writeShort(nameIndex); 152 dataOutputStream.writeShort(signatureIndex); 153 dataOutputStream.writeShort(index); 154 } 155 156 /** 157 * @return Constant pool used by this object. 158 */ 159 public ConstantPool getConstantPool() { 160 return constantPool; 161 } 162 163 /** 164 * @return index of register where variable is stored 165 */ 166 public int getIndex() { 167 return index; 168 } 169 170 /** 171 * @return Variable is valid within getStartPC() .. getStartPC()+getLength() 172 */ 173 public int getLength() { 174 return length; 175 } 176 177 /** 178 * @return Variable name. 179 */ 180 public String getName() { 181 return constantPool.getConstantUtf8(nameIndex).getBytes(); 182 } 183 184 /** 185 * @return Index in constant pool of variable name. 186 */ 187 public int getNameIndex() { 188 return nameIndex; 189 } 190 191 /** 192 * @return index of register where variable was originally stored 193 */ 194 public int getOrigIndex() { 195 return origIndex; 196 } 197 198 /** 199 * @return Signature. 200 */ 201 public String getSignature() { 202 return constantPool.getConstantUtf8(signatureIndex).getBytes(); 203 } 204 205 /** 206 * @return Index in constant pool of variable signature. 207 */ 208 public int getSignatureIndex() { 209 return signatureIndex; 210 } 211 212 /** 213 * @return Start of range where the variable is valid 214 */ 215 public int getStartPC() { 216 return startPc; 217 } 218 219 /** 220 * @param constantPool Constant pool to be used for this object. 221 */ 222 public void setConstantPool(final ConstantPool constantPool) { 223 this.constantPool = constantPool; 224 } 225 226 /** 227 * @param index the index in the local variable table of this variable 228 */ 229 public void setIndex(final int index) { // TODO unused 230 this.index = index; 231 } 232 233 /** 234 * @param length the length of this local variable 235 */ 236 public void setLength(final int length) { 237 this.length = length; 238 } 239 240 /** 241 * @param nameIndex the index into the constant pool for the name of this variable 242 */ 243 public void setNameIndex(final int nameIndex) { // TODO unused 244 this.nameIndex = nameIndex; 245 } 246 247 /** 248 * @param signatureIndex the index into the constant pool for the signature of this variable 249 */ 250 public void setSignatureIndex(final int signatureIndex) { // TODO unused 251 this.signatureIndex = signatureIndex; 252 } 253 254 /** 255 * @param startPc Specify range where the local variable is valid. 256 */ 257 public void setStartPC(final int startPc) { // TODO unused 258 this.startPc = startPc; 259 } 260 261 /** 262 * @return string representation. 263 */ 264 @Override 265 public String toString() { 266 return toStringShared(false); 267 } 268 269 /* 270 * Helper method shared with LocalVariableTypeTable 271 */ 272 String toStringShared(final boolean typeTable) { 273 final String name = getName(); 274 final String signature = Utility.signatureToString(getSignature(), false); 275 final String label = "LocalVariable" + (typeTable ? "Types" : ""); 276 return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")"; 277 } 278}