001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.bytecode;
017:
018: import java.io.DataInputStream;
019: import java.io.IOException;
020: import java.util.Map;
021:
022: /**
023: * <code>LocalVariableTable_attribute</code> or
024: * <code>LocalVariableTypeTable_attribute</code>.
025: */
026: public class LocalVariableAttribute extends AttributeInfo {
027: /**
028: * The name of this attribute <code>"LocalVariableTable"</code>.
029: */
030: public static final String tag = "LocalVariableTable";
031:
032: /**
033: * The name of the attribute <code>"LocalVariableTypeTable"</code>.
034: */
035: public static final String typeTag = "LocalVariableTypeTable";
036:
037: /**
038: * Constructs an empty LocalVariableTable.
039: */
040: public LocalVariableAttribute(ConstPool cp) {
041: this (cp, tag);
042: }
043:
044: /**
045: * Constructs an empty LocalVariableTable.
046: *
047: * @param name the attribute name.
048: * <code>LocalVariableAttribute.tag</code> or
049: * <code>LocalVariableAttribute.typeTag</code>.
050: * @see #tag
051: * @see #typeTag
052: * @since 3.1
053: */
054: public LocalVariableAttribute(ConstPool cp, String name) {
055: super (cp, name, new byte[2]);
056: ByteArray.write16bit(0, info, 0);
057: }
058:
059: LocalVariableAttribute(ConstPool cp, int n, DataInputStream in)
060: throws IOException {
061: super (cp, n, in);
062: }
063:
064: private LocalVariableAttribute(ConstPool cp, String name, byte[] i) {
065: super (cp, name, i);
066: }
067:
068: /**
069: * Appends a new entry to <code>local_variable_table</code>.
070: *
071: * @param startPc <code>start_pc</code>
072: * @param length <code>length</code>
073: * @param nameIndex <code>name_index</code>
074: * @param descriptorIndex <code>descriptor_index</code>
075: * @param index <code>index</code>
076: */
077: public void addEntry(int startPc, int length, int nameIndex,
078: int descriptorIndex, int index) {
079: int size = info.length;
080: byte[] newInfo = new byte[size + 10];
081: ByteArray.write16bit(tableLength() + 1, newInfo, 0);
082: for (int i = 2; i < size; ++i)
083: newInfo[i] = info[i];
084:
085: ByteArray.write16bit(startPc, newInfo, size);
086: ByteArray.write16bit(length, newInfo, size + 2);
087: ByteArray.write16bit(nameIndex, newInfo, size + 4);
088: ByteArray.write16bit(descriptorIndex, newInfo, size + 6);
089: ByteArray.write16bit(index, newInfo, size + 8);
090: info = newInfo;
091: }
092:
093: /**
094: * Returns <code>local_variable_table_length</code>.
095: * This represents the number of entries in the table.
096: */
097: public int tableLength() {
098: return ByteArray.readU16bit(info, 0);
099: }
100:
101: /**
102: * Returns <code>local_variable_table[i].start_pc</code>.
103: * This represents the index into the code array from which the local
104: * variable is effective.
105: *
106: * @param i the i-th entry.
107: */
108: public int startPc(int i) {
109: return ByteArray.readU16bit(info, i * 10 + 2);
110: }
111:
112: /**
113: * Returns <code>local_variable_table[i].length</code>.
114: * This represents the length of the code region in which the local
115: * variable is effective.
116: *
117: * @param i the i-th entry.
118: */
119: public int codeLength(int i) {
120: return ByteArray.readU16bit(info, i * 10 + 4);
121: }
122:
123: /**
124: * Adjusts start_pc and length if bytecode is inserted in a method body.
125: */
126: void shiftPc(int where, int gapLength, boolean exclusive) {
127: int n = tableLength();
128: for (int i = 0; i < n; ++i) {
129: int pos = i * 10 + 2;
130: int pc = ByteArray.readU16bit(info, pos);
131: int len = ByteArray.readU16bit(info, pos + 2);
132:
133: /* if pc == 0, then the local variable is a method parameter.
134: */
135: if (pc > where || (exclusive && pc == where && pc != 0))
136: ByteArray.write16bit(pc + gapLength, info, pos);
137: else if (pc + len > where)
138: ByteArray.write16bit(len + gapLength, info, pos + 2);
139: }
140: }
141:
142: /**
143: * Returns the value of <code>local_variable_table[i].name_index</code>.
144: * This represents the name of the local variable.
145: *
146: * @param i the i-th entry.
147: */
148: public int nameIndex(int i) {
149: return ByteArray.readU16bit(info, i * 10 + 6);
150: }
151:
152: /**
153: * Returns the name of the local variable
154: * specified by <code>local_variable_table[i].name_index</code>.
155: *
156: * @param i the i-th entry.
157: */
158: public String variableName(int i) {
159: return getConstPool().getUtf8Info(nameIndex(i));
160: }
161:
162: /**
163: * Returns the value of
164: * <code>local_variable_table[i].descriptor_index</code>.
165: * This represents the type descriptor of the local variable.
166: * <p>
167: * If this attribute represents a LocalVariableTypeTable attribute,
168: * this method returns the value of
169: * <code>local_variable_type_table[i].signature_index</code>.
170: * It represents the type of the local variable.
171: *
172: * @param i the i-th entry.
173: */
174: public int descriptorIndex(int i) {
175: return ByteArray.readU16bit(info, i * 10 + 8);
176: }
177:
178: /**
179: * This method is equivalent to <code>descriptorIndex()</code>.
180: * If this attribute represents a LocalVariableTypeTable attribute,
181: * this method should be used instead of <code>descriptorIndex()</code>
182: * since the method name is more appropriate.
183: *
184: * @param i the i-th entry.
185: * @see #descriptorIndex(int)
186: */
187: public int signatureIndex(int i) {
188: return descriptorIndex(i);
189: }
190:
191: /**
192: * Returns the type descriptor of the local variable
193: * specified by <code>local_variable_table[i].descriptor_index</code>.
194: * <p>
195: * If this attribute represents a LocalVariableTypeTable attribute,
196: * this method returns the type signature of the local variable
197: * specified by <code>local_variable_type_table[i].signature_index</code>.
198: *
199: * @param i the i-th entry.
200: */
201: public String descriptor(int i) {
202: return getConstPool().getUtf8Info(descriptorIndex(i));
203: }
204:
205: /**
206: * This method is equivalent to <code>descriptor()</code>.
207: * If this attribute represents a LocalVariableTypeTable attribute,
208: * this method should be used instead of <code>descriptor()</code>
209: * since the method name is more appropriate.
210: *
211: * @param i the i-th entry.
212: * @see #descriptor(int)
213: */
214: public String signature(int i) {
215: return descriptor(i);
216: }
217:
218: /**
219: * Returns <code>local_variable_table[i].index</code>.
220: * This represents the index of the local variable.
221: *
222: * @param i the i-th entry.
223: */
224: public int index(int i) {
225: return ByteArray.readU16bit(info, i * 10 + 10);
226: }
227:
228: /**
229: * Makes a copy.
230: *
231: * @param newCp the constant pool table used by the new copy.
232: * @param classnames should be null.
233: */
234: public AttributeInfo copy(ConstPool newCp, Map classnames) {
235: byte[] src = get();
236: byte[] dest = new byte[src.length];
237: ConstPool cp = getConstPool();
238: LocalVariableAttribute attr = new LocalVariableAttribute(newCp,
239: getName(), dest);
240: int n = ByteArray.readU16bit(src, 0);
241: ByteArray.write16bit(n, dest, 0);
242: int j = 2;
243: for (int i = 0; i < n; ++i) {
244: int start = ByteArray.readU16bit(src, j);
245: int len = ByteArray.readU16bit(src, j + 2);
246: int name = ByteArray.readU16bit(src, j + 4);
247: int type = ByteArray.readU16bit(src, j + 6);
248: int index = ByteArray.readU16bit(src, j + 8);
249:
250: ByteArray.write16bit(start, dest, j);
251: ByteArray.write16bit(len, dest, j + 2);
252: if (name != 0)
253: name = cp.copy(name, newCp, null);
254:
255: ByteArray.write16bit(name, dest, j + 4);
256:
257: if (type != 0)
258: type = cp.copy(type, newCp, null);
259:
260: ByteArray.write16bit(type, dest, j + 6);
261: ByteArray.write16bit(index, dest, j + 8);
262: j += 10;
263: }
264:
265: return attr;
266: }
267: }
|