001: /*
002: * Copyright 2000-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: */
017: package org.apache.bcel.generic;
018:
019: import org.apache.bcel.Constants;
020: import org.apache.bcel.classfile.LocalVariable;
021:
022: /**
023: * This class represents a local variable within a method. It contains its
024: * scope, name and type. The generated LocalVariable object can be obtained
025: * with getLocalVariable which needs the instruction list and the constant
026: * pool as parameters.
027: *
028: * @version $Id: LocalVariableGen.java 386056 2006-03-15 11:31:56Z tcurdt $
029: * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
030: * @see LocalVariable
031: * @see MethodGen
032: */
033: public class LocalVariableGen implements InstructionTargeter,
034: NamedAndTyped, Cloneable, java.io.Serializable {
035:
036: private int index;
037: private String name;
038: private Type type;
039: private InstructionHandle start, end;
040:
041: /**
042: * Generate a local variable that with index `index'. Note that double and long
043: * variables need two indexs. Index indices have to be provided by the user.
044: *
045: * @param index index of local variable
046: * @param name its name
047: * @param type its type
048: * @param start from where the instruction is valid (null means from the start)
049: * @param end until where the instruction is valid (null means to the end)
050: */
051: public LocalVariableGen(int index, String name, Type type,
052: InstructionHandle start, InstructionHandle end) {
053: if ((index < 0) || (index > Constants.MAX_SHORT)) {
054: throw new ClassGenException("Invalid index index: " + index);
055: }
056: this .name = name;
057: this .type = type;
058: this .index = index;
059: setStart(start);
060: setEnd(end);
061: }
062:
063: /**
064: * Get LocalVariable object.
065: *
066: * This relies on that the instruction list has already been dumped to byte code or
067: * or that the `setPositions' methods has been called for the instruction list.
068: *
069: * Note that for local variables whose scope end at the last
070: * instruction of the method's code, the JVM specification is ambiguous:
071: * both a start_pc+length ending at the last instruction and
072: * start_pc+length ending at first index beyond the end of the code are
073: * valid.
074: *
075: * @param cp constant pool
076: */
077: public LocalVariable getLocalVariable(ConstantPoolGen cp) {
078: int start_pc = start.getPosition();
079: int length = end.getPosition() - start_pc;
080: if (length > 0) {
081: length += end.getInstruction().getLength();
082: }
083: int name_index = cp.addUtf8(name);
084: int signature_index = cp.addUtf8(type.getSignature());
085: return new LocalVariable(start_pc, length, name_index,
086: signature_index, index, cp.getConstantPool());
087: }
088:
089: public void setIndex(int index) {
090: this .index = index;
091: }
092:
093: public int getIndex() {
094: return index;
095: }
096:
097: public void setName(String name) {
098: this .name = name;
099: }
100:
101: public String getName() {
102: return name;
103: }
104:
105: public void setType(Type type) {
106: this .type = type;
107: }
108:
109: public Type getType() {
110: return type;
111: }
112:
113: public InstructionHandle getStart() {
114: return start;
115: }
116:
117: public InstructionHandle getEnd() {
118: return end;
119: }
120:
121: public void setStart(InstructionHandle start) {
122: BranchInstruction.notifyTarget(this .start, start, this );
123: this .start = start;
124: }
125:
126: public void setEnd(InstructionHandle end) {
127: BranchInstruction.notifyTarget(this .end, end, this );
128: this .end = end;
129: }
130:
131: /**
132: * @param old_ih old target, either start or end
133: * @param new_ih new target
134: */
135: public void updateTarget(InstructionHandle old_ih,
136: InstructionHandle new_ih) {
137: boolean targeted = false;
138: if (start == old_ih) {
139: targeted = true;
140: setStart(new_ih);
141: }
142: if (end == old_ih) {
143: targeted = true;
144: setEnd(new_ih);
145: }
146: if (!targeted) {
147: throw new ClassGenException("Not targeting " + old_ih
148: + ", but {" + start + ", " + end + "}");
149: }
150: }
151:
152: /**
153: * @return true, if ih is target of this variable
154: */
155: public boolean containsTarget(InstructionHandle ih) {
156: return (start == ih) || (end == ih);
157: }
158:
159: /** @return a hash code value for the object.
160: */
161: public int hashCode() {
162: //If the user changes the name or type, problems with the targeter hashmap will occur
163: int hc = index ^ name.hashCode() ^ type.hashCode();
164: return hc;
165: }
166:
167: /**
168: * We consider to local variables to be equal, if the use the same index and
169: * are valid in the same range.
170: */
171: public boolean equals(Object o) {
172: if (!(o instanceof LocalVariableGen)) {
173: return false;
174: }
175: LocalVariableGen l = (LocalVariableGen) o;
176: return (l.index == index) && (l.start == start)
177: && (l.end == end);
178: }
179:
180: public String toString() {
181: return "LocalVariableGen(" + name + ", " + type + ", " + start
182: + ", " + end + ")";
183: }
184:
185: public Object clone() {
186: try {
187: return super .clone();
188: } catch (CloneNotSupportedException e) {
189: System.err.println(e);
190: return null;
191: }
192: }
193: }
|