1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.bcel.generic;
20
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Objects;
24 import java.util.stream.Stream;
25
26 import org.apache.bcel.Const;
27 import org.apache.bcel.classfile.Annotations;
28 import org.apache.bcel.classfile.Attribute;
29 import org.apache.bcel.classfile.Constant;
30 import org.apache.bcel.classfile.ConstantObject;
31 import org.apache.bcel.classfile.ConstantPool;
32 import org.apache.bcel.classfile.ConstantValue;
33 import org.apache.bcel.classfile.Field;
34 import org.apache.bcel.classfile.Utility;
35 import org.apache.bcel.util.BCELComparator;
36
37
38
39
40
41
42
43 public class FieldGen extends FieldGenOrMethodGen {
44
45 private static BCELComparator<FieldGen> bcelComparator = new BCELComparator<FieldGen>() {
46
47 @Override
48 public boolean equals(final FieldGen a, final FieldGen b) {
49 return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
50 }
51
52 @Override
53 public int hashCode(final FieldGen o) {
54 return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
55 }
56 };
57
58
59
60
61
62
63 public static BCELComparator<FieldGen> getComparator() {
64 return bcelComparator;
65 }
66
67
68
69
70
71
72 public static void setComparator(final BCELComparator<FieldGen> comparator) {
73 bcelComparator = comparator;
74 }
75
76 private Object value;
77
78 private List<FieldObserver> observers;
79
80
81
82
83
84
85
86 public FieldGen(final Field field, final ConstantPoolGen cp) {
87 this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
88 final Attribute[] attrs = field.getAttributes();
89 for (final Attribute attr : attrs) {
90 if (attr instanceof ConstantValue) {
91 setValue(((ConstantValue) attr).getConstantValueIndex());
92 } else if (attr instanceof Annotations) {
93 final Annotations runtimeAnnotations = (Annotations) attr;
94 runtimeAnnotations.forEach(element -> addAnnotationEntry(new AnnotationEntryGen(element, cp, false)));
95 } else {
96 addAttribute(attr);
97 }
98 }
99 }
100
101
102
103
104
105
106
107
108
109
110 public FieldGen(final int accessFlags, final Type type, final String name, final ConstantPoolGen cp) {
111 super(accessFlags);
112 setType(type);
113 setName(name);
114 setConstantPool(cp);
115 }
116
117 private void addAnnotationsAsAttribute(final ConstantPoolGen cp) {
118 Stream.of(AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries())).forEach(this::addAttribute);
119 }
120
121 private int addConstant() {
122 switch (super.getType().getType()) {
123 case Const.T_INT:
124 case Const.T_CHAR:
125 case Const.T_BYTE:
126 case Const.T_BOOLEAN:
127 case Const.T_SHORT:
128 return super.getConstantPool().addInteger(((Integer) value).intValue());
129 case Const.T_FLOAT:
130 return super.getConstantPool().addFloat(((Float) value).floatValue());
131 case Const.T_DOUBLE:
132 return super.getConstantPool().addDouble(((Double) value).doubleValue());
133 case Const.T_LONG:
134 return super.getConstantPool().addLong(((Long) value).longValue());
135 case Const.T_REFERENCE:
136 return super.getConstantPool().addString((String) value);
137 default:
138 throw new IllegalStateException("Unhandled : " + super.getType().getType());
139 }
140 }
141
142
143
144
145
146
147 public void addObserver(final FieldObserver o) {
148 if (observers == null) {
149 observers = new ArrayList<>();
150 }
151 observers.add(o);
152 }
153
154
155
156
157 public void cancelInitValue() {
158 value = null;
159 }
160
161 private void checkType(final Type atype) {
162 final Type superType = super.getType();
163 if (superType == null) {
164 throw new ClassGenException("You haven't defined the type of the field yet");
165 }
166 if (!isFinal()) {
167 throw new ClassGenException("Only final fields may have an initial value!");
168 }
169 if (!superType.equals(atype)) {
170 throw new ClassGenException("Types are not compatible: " + superType + " vs. " + atype);
171 }
172 }
173
174
175
176
177
178
179
180 public FieldGen copy(final ConstantPoolGen cp) {
181 final FieldGen fg = (FieldGen) clone();
182 fg.setConstantPool(cp);
183 return fg;
184 }
185
186
187
188
189
190
191
192 @Override
193 public boolean equals(final Object obj) {
194 return obj instanceof FieldGen && bcelComparator.equals(this, (FieldGen) obj);
195 }
196
197
198
199
200
201
202 public Field getField() {
203 final String signature = getSignature();
204 final int nameIndex = super.getConstantPool().addUtf8(super.getName());
205 final int signatureIndex = super.getConstantPool().addUtf8(signature);
206 if (value != null) {
207 checkType(super.getType());
208 final int index = addConstant();
209 addAttribute(new ConstantValue(super.getConstantPool().addUtf8("ConstantValue"), 2, index, super.getConstantPool().getConstantPool()));
210 }
211 addAnnotationsAsAttribute(super.getConstantPool());
212 return new Field(super.getAccessFlags(), nameIndex, signatureIndex, getAttributes(), super.getConstantPool().getConstantPool());
213 }
214
215
216
217
218
219
220 public String getInitValue() {
221 return Objects.toString(value, null);
222 }
223
224 @Override
225 public String getSignature() {
226 return super.getType().getSignature();
227 }
228
229
230
231
232
233
234
235 @Override
236 public int hashCode() {
237 return bcelComparator.hashCode(this);
238 }
239
240
241
242
243
244
245 public void removeObserver(final FieldObserver o) {
246 if (observers != null) {
247 observers.remove(o);
248 }
249 }
250
251
252
253
254
255
256 public void setInitValue(final boolean b) {
257 checkType(Type.BOOLEAN);
258 if (b) {
259 value = Integer.valueOf(1);
260 }
261 }
262
263
264
265
266
267
268 public void setInitValue(final byte b) {
269 checkType(Type.BYTE);
270 if (b != 0) {
271 value = Integer.valueOf(b);
272 }
273 }
274
275
276
277
278
279
280 public void setInitValue(final char c) {
281 checkType(Type.CHAR);
282 if (c != 0) {
283 value = Integer.valueOf(c);
284 }
285 }
286
287
288
289
290
291
292 public void setInitValue(final double d) {
293 checkType(Type.DOUBLE);
294 if (d != 0.0) {
295 value = Double.valueOf(d);
296 }
297 }
298
299
300
301
302
303
304 public void setInitValue(final float f) {
305 checkType(Type.FLOAT);
306 if (f != 0.0) {
307 value = Float.valueOf(f);
308 }
309 }
310
311
312
313
314
315
316 public void setInitValue(final int i) {
317 checkType(Type.INT);
318 if (i != 0) {
319 value = Integer.valueOf(i);
320 }
321 }
322
323
324
325
326
327
328 public void setInitValue(final long l) {
329 checkType(Type.LONG);
330 if (l != 0L) {
331 value = Long.valueOf(l);
332 }
333 }
334
335
336
337
338
339
340 public void setInitValue(final short s) {
341 checkType(Type.SHORT);
342 if (s != 0) {
343 value = Integer.valueOf(s);
344 }
345 }
346
347
348
349
350
351
352 public void setInitValue(final String str) {
353 checkType(ObjectType.getInstance("java.lang.String"));
354 if (str != null) {
355 value = str;
356 }
357 }
358
359 private void setValue(final int index) {
360 final ConstantPool cp = super.getConstantPool().getConstantPool();
361 final Constant c = cp.getConstant(index);
362 value = ((ConstantObject) c).getConstantValue(cp);
363 }
364
365
366
367
368
369
370 @Override
371 public final String toString() {
372
373 String access = Utility.accessToString(super.getAccessFlags());
374 access = access.isEmpty() ? "" : access + " ";
375 final String signature = super.getType().toString();
376 final String name = getName();
377 final StringBuilder buf = new StringBuilder(32);
378 buf.append(access).append(signature).append(" ").append(name);
379 final String value = getInitValue();
380 if (value != null) {
381 buf.append(" = ").append(value);
382 }
383 return buf.toString();
384 }
385
386
387
388
389
390 public void update() {
391 if (observers != null) {
392 for (final FieldObserver observer : observers) {
393 observer.notify(this);
394 }
395 }
396 }
397 }