Source code: com/techtrader/modules/tools/bytecode/FieldInstruction.java
1 package com.techtrader.modules.tools.bytecode;
2
3
4 import java.lang.reflect.Field;
5 import java.io.IOException;
6 import java.io.DataInput;
7 import java.io.DataOutput;
8
9 import com.techtrader.modules.tools.bytecode.lowlevel.FieldEntry;
10 import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
11
12
13 /**
14 * Represents an instruction that takes as an argument a field to operate on.
15 * Examples include GETFIELD, GETSTATIC, SETFIELD, SETSTATIC.
16 *
17 * @author Abe White
18 */
19 public abstract class FieldInstruction
20 extends Instruction
21 {
22 private int _index = 0;
23
24
25 protected FieldInstruction (Code owner, int opcode)
26 {
27 super (owner);
28 _opcode = opcode;
29 }
30
31
32 /**
33 * Get the index of the ComplexEntry in the constant pool describing
34 * the field to operate on.
35 */
36 public int getFieldIndex ()
37 {
38 return _index;
39 }
40
41
42 /**
43 * Set the index of the ComplexEntry in the constant pool describing
44 * the field to operate on.
45 */
46 public void setFieldIndex (int index)
47 {
48 _index = index;
49 }
50
51
52 /**
53 * Set the field to operate on.
54 *
55 * @return this Instruction, for method chaining
56 */
57 public FieldInstruction setField (BCField field)
58 {
59 BCClass ownerType = field.getOwner ();
60 return setField (field.getName (), field.getTypeName (),
61 ownerType.getName ());
62 }
63
64
65 /**
66 * Set the field to operate on.
67 *
68 * @return this Instruction, for method chaining
69 */
70 public FieldInstruction setField (Field field)
71 {
72 return setField (field.getName (), field.getType ().getName (),
73 field.getDeclaringClass ().getName ());
74 }
75
76
77 /**
78 * Set the field to operate on.
79 *
80 * @return this Instruction, for method chaining
81 */
82 public FieldInstruction setField (String name, String type,
83 String ownerType)
84 {
85 String internalType = BCHelper.getInternalForm (type, true);
86 String internalOwner = BCHelper.getInternalForm(ownerType, false);
87
88 _index = _owner.getPool ().setComplex (0, name, internalType,
89 internalOwner, FieldEntry.class);
90
91 return this;
92 }
93
94
95 /**
96 * Set the field to operate on.
97 *
98 * @return this Instruction, for method chaining
99 */
100 public FieldInstruction setField (String name, Class type, String ownerType)
101 {
102 String typeName = (type == null) ? null : type.getName ();
103 return setField (name, typeName, ownerType);
104 }
105
106
107 /**
108 * Set the field to operate on.
109 *
110 * @return this Instruction, for method chaining
111 */
112 public FieldInstruction setField (String name, Class type, Class ownerType)
113 {
114 String typeName = (type == null) ? null : type.getName ();
115 String ownerName = (ownerType == null) ? null : ownerType.getName ();
116 return setField (name, typeName, ownerName);
117 }
118
119
120 /**
121 * Change the field name.
122 *
123 * @return this Instruction, for method chaining
124 */
125 public FieldInstruction setFieldName (String name)
126 {
127 return setField (name, getFieldTypeName (), getFieldOwnerTypeName ());
128 }
129
130
131 /**
132 * Return true if the field is a member of the current class.
133 */
134 public boolean isFieldInCurrentClass ()
135 {
136 BCClass type = ((BCMethod) _owner.getOwner ()).getOwner ();
137 return type.getName ().equals (getFieldOwnerTypeName ());
138 }
139
140
141 /**
142 * If the field is a member of the current class, then this method will
143 * retrieve the BCField object for it; otherwise it will return null.
144 */
145 public BCField getField ()
146 {
147 if (!isFieldInCurrentClass ())
148 return null;
149
150 return ((BCMethod) _owner.getOwner ()).getOwner ().
151 getField (getFieldName ());
152 }
153
154
155 /**
156 * Get the nam of the field to operate on.
157 */
158 public String getFieldName ()
159 {
160 return _owner.getPool ().getComplexName (_index);
161 }
162
163
164 /**
165 * Get the type of the field.
166 */
167 public String getFieldTypeName ()
168 {
169 return BCHelper.getExternalForm
170 (_owner.getPool ().getComplexTypeName (_index), true);
171 }
172
173
174 /**
175 * Get the type of the field.
176 */
177 public Class getFieldType ()
178 throws ClassNotFoundException
179 {
180 return BCHelper.classForName
181 (_owner.getPool ().getComplexTypeName (_index));
182 }
183
184
185 /**
186 * Get the type of the field.
187 */
188 public String getFieldOwnerTypeName ()
189 {
190 return BCHelper.getExternalForm
191 (_owner.getPool ().getComplexOwnerTypeName (_index), true);
192 }
193
194
195 /**
196 * Get the type of the field.
197 */
198 public Class getFieldOwnerType ()
199 throws ClassNotFoundException
200 {
201 return BCHelper.classForName
202 (_owner.getPool ().getComplexOwnerTypeName (_index));
203 }
204
205
206 /**
207 * FieldInstructions are equal if the field they reference is the same,
208 * or if the field of either is unset.
209 */
210 public boolean equals (Object other)
211 {
212 if (other == this)
213 return true;
214 if (!(other instanceof FieldInstruction))
215 return false;
216 if (!super.equals (other))
217 return false;
218
219 FieldInstruction ins = (FieldInstruction) other;
220
221 String s1 = getFieldName ();
222 String s2 = ins.getFieldName ();
223 if (!(s1.length () == 0 || s2.length () == 0 || s1.equals (s2)))
224 return false;
225
226 s1 = getFieldTypeName ();
227 s2 = ins.getFieldTypeName ();
228 if (!(s1.length () == 0 || s2.length () == 0 || s1.equals (s2)))
229 return false;
230
231 s1 = getFieldOwnerTypeName ();
232 s2 = ins.getFieldOwnerTypeName ();
233 if (!(s1.length () == 0 || s2.length () == 0 || s1.equals (s2)))
234 return false;
235
236 return true;
237 }
238
239
240 public int getLength ()
241 {
242 return super.getLength () + 2;
243 }
244
245
246 protected void copy (Instruction orig)
247 {
248 super.copy (orig);
249 FieldInstruction origFI = (FieldInstruction) orig;
250
251 setField (origFI.getFieldName (), origFI.getFieldTypeName (),
252 origFI.getFieldOwnerTypeName ());
253 }
254
255
256 protected void readData (DataInput in)
257 throws IOException
258 {
259 _index = in.readUnsignedShort ();
260 }
261
262
263 protected void writeData (DataOutput out)
264 throws IOException
265 {
266 out.writeShort (_index);
267 }
268 }