View Javadoc

1   /*
2    * Copyright  2000-2004 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License"); 
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License. 
15   *
16   */
17  package org.apache.bcel.generic;
18  
19  import org.apache.bcel.Constants;
20  import org.apache.bcel.classfile.LocalVariable;
21  
22  /*** 
23   * This class represents a local variable within a method. It contains its
24   * scope, name and type. The generated LocalVariable object can be obtained
25   * with getLocalVariable which needs the instruction list and the constant
26   * pool as parameters.
27   *
28   * @version $Id: LocalVariableGen.java 386056 2006-03-15 11:31:56Z tcurdt $
29   * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
30   * @see     LocalVariable
31   * @see     MethodGen
32   */
33  public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable,
34          java.io.Serializable {
35  
36      private int index;
37      private String name;
38      private Type type;
39      private InstructionHandle start, end;
40  
41  
42      /***
43       * Generate a local variable that with index `index'. Note that double and long
44       * variables need two indexs. Index indices have to be provided by the user.
45       *
46       * @param index index of local variable
47       * @param name its name
48       * @param type its type
49       * @param start from where the instruction is valid (null means from the start)
50       * @param end until where the instruction is valid (null means to the end)
51       */
52      public LocalVariableGen(int index, String name, Type type, InstructionHandle start,
53              InstructionHandle end) {
54          if ((index < 0) || (index > Constants.MAX_SHORT)) {
55              throw new ClassGenException("Invalid index index: " + index);
56          }
57          this.name = name;
58          this.type = type;
59          this.index = index;
60          setStart(start);
61          setEnd(end);
62      }
63  
64  
65      /***
66       * Get LocalVariable object.
67       *
68       * This relies on that the instruction list has already been dumped to byte code or
69       * or that the `setPositions' methods has been called for the instruction list.
70       *
71       * Note that for local variables whose scope end at the last
72       * instruction of the method's code, the JVM specification is ambiguous:
73       * both a start_pc+length ending at the last instruction and
74       * start_pc+length ending at first index beyond the end of the code are
75       * valid.
76       *
77       * @param cp constant pool
78       */
79      public LocalVariable getLocalVariable( ConstantPoolGen cp ) {
80          int start_pc = start.getPosition();
81          int length = end.getPosition() - start_pc;
82          if (length > 0) {
83              length += end.getInstruction().getLength();
84          }
85          int name_index = cp.addUtf8(name);
86          int signature_index = cp.addUtf8(type.getSignature());
87          return new LocalVariable(start_pc, length, name_index, signature_index, index, cp
88                  .getConstantPool());
89      }
90  
91  
92      public void setIndex( int index ) {
93          this.index = index;
94      }
95  
96  
97      public int getIndex() {
98          return index;
99      }
100 
101 
102     public void setName( String name ) {
103         this.name = name;
104     }
105 
106 
107     public String getName() {
108         return name;
109     }
110 
111 
112     public void setType( Type type ) {
113         this.type = type;
114     }
115 
116 
117     public Type getType() {
118         return type;
119     }
120 
121 
122     public InstructionHandle getStart() {
123         return start;
124     }
125 
126 
127     public InstructionHandle getEnd() {
128         return end;
129     }
130 
131 
132     public void setStart( InstructionHandle start ) {
133         BranchInstruction.notifyTarget(this.start, start, this);
134         this.start = start;
135     }
136 
137 
138     public void setEnd( InstructionHandle end ) {
139         BranchInstruction.notifyTarget(this.end, end, this);
140         this.end = end;
141     }
142 
143 
144     /***
145      * @param old_ih old target, either start or end
146      * @param new_ih new target
147      */
148     public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
149         boolean targeted = false;
150         if (start == old_ih) {
151             targeted = true;
152             setStart(new_ih);
153         }
154         if (end == old_ih) {
155             targeted = true;
156             setEnd(new_ih);
157         }
158         if (!targeted) {
159             throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end
160                     + "}");
161         }
162     }
163 
164 
165     /***
166      * @return true, if ih is target of this variable
167      */
168     public boolean containsTarget( InstructionHandle ih ) {
169         return (start == ih) || (end == ih);
170     }
171 
172 
173     /*** @return a hash code value for the object.
174      */
175     public int hashCode() {
176         //If the user changes the name or type, problems with the targeter hashmap will occur
177         int hc = index ^ name.hashCode() ^ type.hashCode();
178         return hc;
179     }
180 
181 
182     /***
183      * We consider to local variables to be equal, if the use the same index and
184      * are valid in the same range.
185      */
186     public boolean equals( Object o ) {
187         if (!(o instanceof LocalVariableGen)) {
188             return false;
189         }
190         LocalVariableGen l = (LocalVariableGen) o;
191         return (l.index == index) && (l.start == start) && (l.end == end);
192     }
193 
194 
195     public String toString() {
196         return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")";
197     }
198 
199 
200     public Object clone() {
201         try {
202             return super.clone();
203         } catch (CloneNotSupportedException e) {
204             System.err.println(e);
205             return null;
206         }
207     }
208 }