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 * 017 */ 018package org.apache.bcel.classfile; 019 020import java.io.DataInput; 021import java.io.DataOutputStream; 022import java.io.IOException; 023 024import org.apache.bcel.Constants; 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 private int startPc; // Range in which the variable is valid 041 private int length; 042 private int nameIndex; // Index in constant pool of variable name 043 // Technically, a decscriptor_index for a local variable table entry 044 // and a signatureIndex for a local variable type table entry. 045 private int signatureIndex; // Index of variable signature 046 private int index; /* 047 * Variable is index'th local variable on this method's frame. 048 */ 049 private ConstantPool constantPool; 050 private int origIndex; // never changes; used to match up with LocalVariableTypeTable entries 051 052 /** 053 * Constructs object from file stream. 054 * 055 * @param file Input stream 056 * @throws IOException if an I/O error occurs. 057 */ 058 LocalVariable(final DataInput file, final ConstantPool constant_pool) throws IOException { 059 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constant_pool); 060 } 061 062 /** 063 * @param startPc Range in which the variable 064 * @param length ... is valid 065 * @param nameIndex Index in constant pool of variable name 066 * @param signatureIndex Index of variable's signature 067 * @param index Variable is `index'th local variable on the method's frame 068 * @param constantPool Array of constants 069 */ 070 public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) { 071 this.startPc = startPc; 072 this.length = length; 073 this.nameIndex = nameIndex; 074 this.signatureIndex = signatureIndex; 075 this.index = index; 076 this.constantPool = constantPool; 077 this.origIndex = index; 078 } 079 080 /** 081 * @param startPc Range in which the variable 082 * @param length ... is valid 083 * @param nameIndex Index in constant pool of variable name 084 * @param signatureIndex Index of variable's signature 085 * @param index Variable is `index'th local variable on the method's frame 086 * @param constantPool Array of constants 087 * @param origIndex Variable is `index'th local variable on the method's frame prior to any changes 088 */ 089 public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool, 090 final int origIndex) { 091 this.startPc = startPc; 092 this.length = length; 093 this.nameIndex = nameIndex; 094 this.signatureIndex = signatureIndex; 095 this.index = index; 096 this.constantPool = constantPool; 097 this.origIndex = origIndex; 098 } 099 100 /** 101 * Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for 102 * a physical copy. 103 * 104 * @param localVariable Another LocalVariable. 105 */ 106 public LocalVariable(final LocalVariable localVariable) { 107 this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(), 108 localVariable.getConstantPool()); 109 this.origIndex = localVariable.getOrigIndex(); 110 } 111 112 /** 113 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 114 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 115 * 116 * @param v Visitor object 117 */ 118 @Override 119 public void accept(final Visitor v) { 120 v.visitLocalVariable(this); 121 } 122 123 /** 124 * @return deep copy of this object 125 */ 126 public LocalVariable copy() { 127 try { 128 return (LocalVariable) clone(); 129 } catch (final CloneNotSupportedException e) { 130 // TODO should this throw? 131 } 132 return null; 133 } 134 135 /** 136 * Dumps local variable to file stream in binary format. 137 * 138 * @param dataOutputStream Output file stream 139 * @throws IOException if an I/O error occurs. 140 * @see java.io.FilterOutputStream#out 141 */ 142 public void dump(final DataOutputStream dataOutputStream) throws IOException { 143 dataOutputStream.writeShort(startPc); 144 dataOutputStream.writeShort(length); 145 dataOutputStream.writeShort(nameIndex); 146 dataOutputStream.writeShort(signatureIndex); 147 dataOutputStream.writeShort(index); 148 } 149 150 /** 151 * @return Constant pool used by this object. 152 */ 153 public ConstantPool getConstantPool() { 154 return constantPool; 155 } 156 157 /** 158 * @return index of register where variable is stored 159 */ 160 public int getIndex() { 161 return index; 162 } 163 164 /** 165 * @return Variable is valid within getStartPC() .. getStartPC()+getLength() 166 */ 167 public int getLength() { 168 return length; 169 } 170 171 /** 172 * @return Variable name. 173 */ 174 public String getName() { 175 return constantPool.getConstantUtf8(nameIndex).getBytes(); 176 } 177 178 /** 179 * @return Index in constant pool of variable name. 180 */ 181 public int getNameIndex() { 182 return nameIndex; 183 } 184 185 /** 186 * @return index of register where variable was originally stored 187 */ 188 public int getOrigIndex() { 189 return origIndex; 190 } 191 192 /** 193 * @return Signature. 194 */ 195 public String getSignature() { 196 return constantPool.getConstantUtf8(signatureIndex).getBytes(); 197 } 198 199 /** 200 * @return Index in constant pool of variable signature. 201 */ 202 public int getSignatureIndex() { 203 return signatureIndex; 204 } 205 206 /** 207 * @return Start of range where the variable is valid 208 */ 209 public int getStartPC() { 210 return startPc; 211 } 212 213 /** 214 * @param constantPool Constant pool to be used for this object. 215 */ 216 public void setConstantPool(final ConstantPool constantPool) { 217 this.constantPool = constantPool; 218 } 219 220 /** 221 * @param index the index in the local variable table of this variable 222 */ 223 public void setIndex(final int index) { // TODO unused 224 this.index = index; 225 } 226 227 /** 228 * @param length the length of this local variable 229 */ 230 public void setLength(final int length) { 231 this.length = length; 232 } 233 234 /** 235 * @param nameIndex the index into the constant pool for the name of this variable 236 */ 237 public void setNameIndex(final int nameIndex) { // TODO unused 238 this.nameIndex = nameIndex; 239 } 240 241 /** 242 * @param signatureIndex the index into the constant pool for the signature of this variable 243 */ 244 public void setSignatureIndex(final int signatureIndex) { // TODO unused 245 this.signatureIndex = signatureIndex; 246 } 247 248 /** 249 * @param startPc Specify range where the local variable is valid. 250 */ 251 public void setStartPC(final int startPc) { // TODO unused 252 this.startPc = startPc; 253 } 254 255 /** 256 * @return string representation. 257 */ 258 @Override 259 public String toString() { 260 return toStringShared(false); 261 } 262 263 /* 264 * Helper method shared with LocalVariableTypeTable 265 */ 266 String toStringShared(final boolean typeTable) { 267 final String name = getName(); 268 final String signature = Utility.signatureToString(getSignature(), false); 269 final String label = "LocalVariable" + (typeTable ? "Types" : ""); 270 return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")"; 271 } 272}