KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > classfmt > FieldInfo


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.classfmt;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
15 import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
16 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
17 import org.eclipse.jdt.internal.compiler.impl.*;
18 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
19 import org.eclipse.jdt.internal.compiler.util.Util;
20
21 public class FieldInfo extends ClassFileStruct implements IBinaryField, Comparable JavaDoc {
22     protected int accessFlags;
23     protected int attributeBytes;
24     protected Constant constant;
25     protected char[] descriptor;
26     protected char[] name;
27     protected char[] signature;
28     protected int signatureUtf8Offset;
29     protected long tagBits;
30     protected Object JavaDoc wrappedConstantValue;
31
32 public static FieldInfo createField(byte classFileBytes[], int offsets[], int offset) {
33     FieldInfo fieldInfo = new FieldInfo(classFileBytes, offsets, offset);
34     AnnotationInfo[] annotations = fieldInfo.readAttributes();
35     if (annotations == null)
36         return fieldInfo;
37     return new FieldInfoWithAnnotation(fieldInfo, annotations);
38 }
39
40 /**
41  * @param classFileBytes byte[]
42  * @param offsets int[]
43  * @param offset int
44  */

45 protected FieldInfo (byte classFileBytes[], int offsets[], int offset) {
46     super(classFileBytes, offsets, offset);
47     this.accessFlags = -1;
48     this.signatureUtf8Offset = -1;
49 }
50 private AnnotationInfo[] decodeAnnotations(int offset, boolean runtimeVisible) {
51     int numberOfAnnotations = u2At(offset + 6);
52     if (numberOfAnnotations > 0) {
53         int readOffset = offset + 8;
54         AnnotationInfo[] newInfos = null;
55         int newInfoCount = 0;
56         for (int i = 0; i < numberOfAnnotations; i++) {
57             // With the last parameter being 'false', the data structure will not be flushed out
58
AnnotationInfo newInfo = new AnnotationInfo(this.reference, this.constantPoolOffsets,
59                 readOffset + this.structOffset, runtimeVisible, false);
60             readOffset += newInfo.readOffset;
61             long standardTagBits = newInfo.standardAnnotationTagBits;
62             if (standardTagBits != 0) {
63                 this.tagBits |= standardTagBits;
64             } else {
65                 if (newInfos == null)
66                     newInfos = new AnnotationInfo[numberOfAnnotations - i];
67                 newInfos[newInfoCount++] = newInfo;
68             }
69         }
70         if (newInfos != null) {
71             if (newInfoCount != newInfos.length)
72                 System.arraycopy(newInfos, 0, newInfos = new AnnotationInfo[newInfoCount], 0, newInfoCount);
73             return newInfos;
74         }
75     }
76     return null; // nothing to record
77
}
78 public int compareTo(Object JavaDoc o) {
79     if (!(o instanceof FieldInfo)) {
80         throw new ClassCastException JavaDoc();
81     }
82     return new String JavaDoc(this.getName()).compareTo(new String JavaDoc(((FieldInfo) o).getName()));
83 }
84 /**
85  * Return the constant of the field.
86  * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
87  * @return org.eclipse.jdt.internal.compiler.impl.Constant
88  */

89 public Constant getConstant() {
90     if (constant == null) {
91         // read constant
92
readConstantAttribute();
93     }
94     return constant;
95 }
96 public char[] getGenericSignature() {
97     if (this.signatureUtf8Offset != -1) {
98         if (this.signature == null) {
99             // decode the signature
100
this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
101         }
102         return this.signature;
103     }
104     return null;
105 }
106 /**
107  * Answer an int whose bits are set according the access constants
108  * defined by the VM spec.
109  * Set the AccDeprecated and AccSynthetic bits if necessary
110  * @return int
111  */

112 public int getModifiers() {
113     if (this.accessFlags == -1) {
114         // compute the accessflag. Don't forget the deprecated attribute
115
this.accessFlags = u2At(0);
116         readModifierRelatedAttributes();
117     }
118     return this.accessFlags;
119 }
120 /**
121  * Answer the name of the field.
122  * @return char[]
123  */

124 public char[] getName() {
125     if (name == null) {
126         // read the name
127
int utf8Offset = constantPoolOffsets[u2At(2)] - structOffset;
128         name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
129     }
130     return name;
131 }
132 public long getTagBits() {
133     return this.tagBits;
134 }
135 /**
136  * Answer the resolved name of the receiver's type in the
137  * class file format as specified in section 4.3.2 of the Java 2 VM spec.
138  *
139  * For example:
140  * - java.lang.String is Ljava/lang/String;
141  * - an int is I
142  * - a 2 dimensional array of strings is [[Ljava/lang/String;
143  * - an array of floats is [F
144  * @return char[]
145  */

146 public char[] getTypeName() {
147     if (descriptor == null) {
148         // read the signature
149
int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
150         descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
151     }
152     return descriptor;
153 }
154 /**
155  * @return the annotations or null if there is none.
156  */

157 public IBinaryAnnotation[] getAnnotations() {
158     return null;
159 }
160 /**
161  * Return a wrapper that contains the constant of the field.
162  * @return java.lang.Object
163  */

164 public Object JavaDoc getWrappedConstantValue() {
165
166     if (this.wrappedConstantValue == null) {
167         if (hasConstant()) {
168             Constant fieldConstant = getConstant();
169             switch (fieldConstant.typeID()) {
170                 case TypeIds.T_int :
171                     this.wrappedConstantValue = new Integer JavaDoc(fieldConstant.intValue());
172                     break;
173                 case TypeIds.T_byte :
174                     this.wrappedConstantValue = new Byte JavaDoc(fieldConstant.byteValue());
175                     break;
176                 case TypeIds.T_short :
177                     this.wrappedConstantValue = new Short JavaDoc(fieldConstant.shortValue());
178                     break;
179                 case TypeIds.T_char :
180                     this.wrappedConstantValue = new Character JavaDoc(fieldConstant.charValue());
181                     break;
182                 case TypeIds.T_float :
183                     this.wrappedConstantValue = new Float JavaDoc(fieldConstant.floatValue());
184                     break;
185                 case TypeIds.T_double :
186                     this.wrappedConstantValue = new Double JavaDoc(fieldConstant.doubleValue());
187                     break;
188                 case TypeIds.T_boolean :
189                     this.wrappedConstantValue = Util.toBoolean(fieldConstant.booleanValue());
190                     break;
191                 case TypeIds.T_long :
192                     this.wrappedConstantValue = new Long JavaDoc(fieldConstant.longValue());
193                     break;
194                 case TypeIds.T_JavaLangString :
195                     this.wrappedConstantValue = fieldConstant.stringValue();
196             }
197         }
198     }
199     return this.wrappedConstantValue;
200 }
201 /**
202  * Return true if the field has a constant value attribute, false otherwise.
203  * @return boolean
204  */

205 public boolean hasConstant() {
206     return getConstant() != Constant.NotAConstant;
207 }
208 /**
209  * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
210  * will be therefore fully initialized and we can get rid of the bytes.
211  */

212 protected void initialize() {
213     getModifiers();
214     getName();
215     getConstant();
216     getTypeName();
217     getGenericSignature();
218     reset();
219 }
220 /**
221  * Return true if the field is a synthetic field, false otherwise.
222  * @return boolean
223  */

224 public boolean isSynthetic() {
225     return (getModifiers() & ClassFileConstants.AccSynthetic) != 0;
226 }
227 private AnnotationInfo[] readAttributes() {
228     int attributesCount = u2At(6);
229     int readOffset = 8;
230     AnnotationInfo[] annotations = null;
231     for (int i = 0; i < attributesCount; i++) {
232         // check the name of each attribute
233
int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.structOffset;
234         char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
235         if (attributeName.length > 0) {
236             switch(attributeName[0]) {
237                 case 'S' :
238                     if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName))
239                         this.signatureUtf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)] - this.structOffset;
240                     break;
241                 case 'R' :
242                     AnnotationInfo[] decodedAnnotations = null;
243                     if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) {
244                         decodedAnnotations = decodeAnnotations(readOffset, true);
245                     } else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
246                         decodedAnnotations = decodeAnnotations(readOffset, false);
247                     }
248                     if (decodedAnnotations != null) {
249                         if (annotations == null) {
250                             annotations = decodedAnnotations;
251                         } else {
252                             int length = annotations.length;
253                             AnnotationInfo[] combined = new AnnotationInfo[length + decodedAnnotations.length];
254                             System.arraycopy(annotations, 0, combined, 0, length);
255                             System.arraycopy(decodedAnnotations, 0, combined, length, decodedAnnotations.length);
256                             annotations = combined;
257                         }
258                     }
259             }
260         }
261         readOffset += (6 + u4At(readOffset + 2));
262     }
263     this.attributeBytes = readOffset;
264     return annotations;
265 }
266 private void readConstantAttribute() {
267     int attributesCount = u2At(6);
268     int readOffset = 8;
269     boolean isConstant = false;
270     for (int i = 0; i < attributesCount; i++) {
271         int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
272         char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
273         if (CharOperation
274             .equals(attributeName, AttributeNamesConstants.ConstantValueName)) {
275             isConstant = true;
276             // read the right constant
277
int relativeOffset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
278             switch (u1At(relativeOffset)) {
279                 case ClassFileConstants.IntegerTag :
280                     char[] sign = getTypeName();
281                     if (sign.length == 1) {
282                         switch (sign[0]) {
283                             case 'Z' : // boolean constant
284
constant = BooleanConstant.fromValue(i4At(relativeOffset + 1) == 1);
285                                 break;
286                             case 'I' : // integer constant
287
constant = IntConstant.fromValue(i4At(relativeOffset + 1));
288                                 break;
289                             case 'C' : // char constant
290
constant = CharConstant.fromValue((char) i4At(relativeOffset + 1));
291                                 break;
292                             case 'B' : // byte constant
293
constant = ByteConstant.fromValue((byte) i4At(relativeOffset + 1));
294                                 break;
295                             case 'S' : // short constant
296
constant = ShortConstant.fromValue((short) i4At(relativeOffset + 1));
297                                 break;
298                             default:
299                                 constant = Constant.NotAConstant;
300                         }
301                     } else {
302                         constant = Constant.NotAConstant;
303                     }
304                     break;
305                 case ClassFileConstants.FloatTag :
306                     constant = FloatConstant.fromValue(floatAt(relativeOffset + 1));
307                     break;
308                 case ClassFileConstants.DoubleTag :
309                     constant = DoubleConstant.fromValue(doubleAt(relativeOffset + 1));
310                     break;
311                 case ClassFileConstants.LongTag :
312                     constant = LongConstant.fromValue(i8At(relativeOffset + 1));
313                     break;
314                 case ClassFileConstants.StringTag :
315                     utf8Offset = constantPoolOffsets[u2At(relativeOffset + 1)] - structOffset;
316                     constant =
317                         StringConstant.fromValue(
318                             String.valueOf(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))));
319                     break;
320             }
321         }
322         readOffset += (6 + u4At(readOffset + 2));
323     }
324     if (!isConstant) {
325         constant = Constant.NotAConstant;
326     }
327 }
328 private void readModifierRelatedAttributes() {
329     int attributesCount = u2At(6);
330     int readOffset = 8;
331     for (int i = 0; i < attributesCount; i++) {
332         int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
333         char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
334         // test added for obfuscated .class file. See 79772
335
if (attributeName.length != 0) {
336             switch(attributeName[0]) {
337                 case 'D' :
338                     if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName))
339                         this.accessFlags |= ClassFileConstants.AccDeprecated;
340                     break;
341                 case 'S' :
342                     if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName))
343                         this.accessFlags |= ClassFileConstants.AccSynthetic;
344                     break;
345             }
346         }
347         readOffset += (6 + u4At(readOffset + 2));
348     }
349 }
350 /**
351  * Answer the size of the receiver in bytes.
352  *
353  * @return int
354  */

355 public int sizeInBytes() {
356     return attributeBytes;
357 }
358 public void throwFormatException() throws ClassFormatException {
359     throw new ClassFormatException(ClassFormatException.ErrBadFieldInfo);
360 }
361 public String JavaDoc toString() {
362     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(this.getClass().getName());
363     toStringContent(buffer);
364     return buffer.toString();
365 }
366 protected void toStringContent(StringBuffer JavaDoc buffer) {
367     int modifiers = getModifiers();
368     buffer
369         .append('{')
370         .append(
371             ((modifiers & ClassFileConstants.AccDeprecated) != 0 ? "deprecated " : Util.EMPTY_STRING) //$NON-NLS-1$
372
+ ((modifiers & 0x0001) == 1 ? "public " : Util.EMPTY_STRING) //$NON-NLS-1$
373
+ ((modifiers & 0x0002) == 0x0002 ? "private " : Util.EMPTY_STRING) //$NON-NLS-1$
374
+ ((modifiers & 0x0004) == 0x0004 ? "protected " : Util.EMPTY_STRING) //$NON-NLS-1$
375
+ ((modifiers & 0x0008) == 0x000008 ? "static " : Util.EMPTY_STRING) //$NON-NLS-1$
376
+ ((modifiers & 0x0010) == 0x0010 ? "final " : Util.EMPTY_STRING) //$NON-NLS-1$
377
+ ((modifiers & 0x0040) == 0x0040 ? "volatile " : Util.EMPTY_STRING) //$NON-NLS-1$
378
+ ((modifiers & 0x0080) == 0x0080 ? "transient " : Util.EMPTY_STRING)) //$NON-NLS-1$
379
.append(getTypeName())
380         .append(' ')
381         .append(getName())
382         .append(' ')
383         .append(getConstant())
384         .append('}')
385         .toString();
386 }
387 }
388
Popular Tags