001: /*
002: * Copyright 2004 Brian S O'Neill
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.cojen.classfile;
018:
019: import java.util.ArrayList;
020: import java.util.List;
021: import java.io.DataInput;
022: import java.io.DataOutput;
023: import java.io.IOException;
024: import java.lang.reflect.Modifier;
025: import org.cojen.classfile.attribute.Annotation;
026: import org.cojen.classfile.attribute.AnnotationsAttr;
027: import org.cojen.classfile.attribute.ConstantValueAttr;
028: import org.cojen.classfile.attribute.DeprecatedAttr;
029: import org.cojen.classfile.attribute.RuntimeInvisibleAnnotationsAttr;
030: import org.cojen.classfile.attribute.RuntimeVisibleAnnotationsAttr;
031: import org.cojen.classfile.attribute.SignatureAttr;
032: import org.cojen.classfile.attribute.SyntheticAttr;
033: import org.cojen.classfile.constant.ConstantUTFInfo;
034:
035: /**
036: * This class corresponds to the field_info structure as defined in
037: * section 4.5 of <i>The Java Virtual Machine Specification</i>.
038: *
039: * @author Brian S O'Neill
040: * @see ClassFile
041: */
042: public class FieldInfo {
043: private ClassFile mParent;
044: private ConstantPool mCp;
045:
046: private String mName;
047: private TypeDesc mType;
048:
049: private Modifiers mModifiers;
050:
051: private ConstantUTFInfo mNameConstant;
052: private ConstantUTFInfo mDescriptorConstant;
053:
054: private List mAttributes = new ArrayList(2);
055:
056: private ConstantValueAttr mConstant;
057:
058: FieldInfo(ClassFile parent, Modifiers modifiers, String name,
059: TypeDesc type) {
060:
061: mParent = parent;
062: mCp = parent.getConstantPool();
063: mName = name;
064: mType = type;
065:
066: mModifiers = modifiers;
067: mNameConstant = mCp.addConstantUTF(name);
068: mDescriptorConstant = mCp.addConstantUTF(type.getDescriptor());
069: }
070:
071: private FieldInfo(ClassFile parent, int modifier,
072: ConstantUTFInfo nameConstant, ConstantUTFInfo descConstant) {
073:
074: mParent = parent;
075: mCp = parent.getConstantPool();
076: mName = nameConstant.getValue();
077: mType = TypeDesc.forDescriptor(descConstant.getValue());
078:
079: mModifiers = Modifiers.getInstance(modifier);
080: mNameConstant = nameConstant;
081: mDescriptorConstant = descConstant;
082: }
083:
084: /**
085: * Returns the parent ClassFile for this FieldInfo.
086: */
087: public ClassFile getClassFile() {
088: return mParent;
089: }
090:
091: /**
092: * Returns the name of this field.
093: */
094: public String getName() {
095: return mName;
096: }
097:
098: /**
099: * Returns the type of this field.
100: */
101: public TypeDesc getType() {
102: return mType;
103: }
104:
105: /**
106: * Returns this field's modifiers.
107: */
108: public Modifiers getModifiers() {
109: return mModifiers;
110: }
111:
112: public void setModifiers(Modifiers modifiers) {
113: mModifiers = modifiers;
114: }
115:
116: /**
117: * Returns a constant from the constant pool with this field's name.
118: */
119: public ConstantUTFInfo getNameConstant() {
120: return mNameConstant;
121: }
122:
123: /**
124: * Returns a constant from the constant pool with this field's type
125: * descriptor string.
126: * @see TypeDesc
127: */
128: public ConstantUTFInfo getDescriptorConstant() {
129: return mDescriptorConstant;
130: }
131:
132: /**
133: * Returns the constant value for this field or null if no constant set.
134: */
135: public ConstantInfo getConstantValue() {
136: if (mConstant == null) {
137: return null;
138: } else {
139: return mConstant.getConstant();
140: }
141: }
142:
143: public boolean isSynthetic() {
144: for (int i = mAttributes.size(); --i >= 0;) {
145: Object obj = mAttributes.get(i);
146: if (obj instanceof SyntheticAttr) {
147: return true;
148: }
149: }
150: return false;
151: }
152:
153: public boolean isDeprecated() {
154: for (int i = mAttributes.size(); --i >= 0;) {
155: Object obj = mAttributes.get(i);
156: if (obj instanceof DeprecatedAttr) {
157: return true;
158: }
159: }
160: return false;
161: }
162:
163: /**
164: * Returns all the runtime invisible annotations defined for this class
165: * file, or an empty array if none.
166: */
167: public Annotation[] getRuntimeInvisibleAnnotations() {
168: for (int i = mAttributes.size(); --i >= 0;) {
169: Object obj = mAttributes.get(i);
170: if (obj instanceof RuntimeInvisibleAnnotationsAttr) {
171: return ((AnnotationsAttr) obj).getAnnotations();
172: }
173: }
174: return new Annotation[0];
175: }
176:
177: /**
178: * Returns all the runtime visible annotations defined for this class file,
179: * or an empty array if none.
180: */
181: public Annotation[] getRuntimeVisibleAnnotations() {
182: for (int i = mAttributes.size(); --i >= 0;) {
183: Object obj = mAttributes.get(i);
184: if (obj instanceof RuntimeVisibleAnnotationsAttr) {
185: return ((AnnotationsAttr) obj).getAnnotations();
186: }
187: }
188: return new Annotation[0];
189: }
190:
191: /**
192: * Add a runtime invisible annotation.
193: */
194: public Annotation addRuntimeInvisibleAnnotation(TypeDesc type) {
195: AnnotationsAttr attr = null;
196: for (int i = mAttributes.size(); --i >= 0;) {
197: Object obj = mAttributes.get(i);
198: if (obj instanceof RuntimeInvisibleAnnotationsAttr) {
199: attr = (AnnotationsAttr) obj;
200: }
201: }
202: if (attr == null) {
203: attr = new RuntimeInvisibleAnnotationsAttr(mCp);
204: addAttribute(attr);
205: }
206: Annotation ann = new Annotation(mCp);
207: ann.setType(type);
208: attr.addAnnotation(ann);
209: return ann;
210: }
211:
212: /**
213: * Add a runtime visible annotation.
214: */
215: public Annotation addRuntimeVisibleAnnotation(TypeDesc type) {
216: AnnotationsAttr attr = null;
217: for (int i = mAttributes.size(); --i >= 0;) {
218: Object obj = mAttributes.get(i);
219: if (obj instanceof RuntimeVisibleAnnotationsAttr) {
220: attr = (AnnotationsAttr) obj;
221: }
222: }
223: if (attr == null) {
224: attr = new RuntimeVisibleAnnotationsAttr(mCp);
225: addAttribute(attr);
226: }
227: Annotation ann = new Annotation(mCp);
228: ann.setType(type);
229: attr.addAnnotation(ann);
230: return ann;
231: }
232:
233: /**
234: * Returns the signature attribute of this field, or null if none is
235: * defined.
236: */
237: // TODO: Eventually remove this method
238: public SignatureAttr getSignatureAttr() {
239: for (int i = mAttributes.size(); --i >= 0;) {
240: Object obj = mAttributes.get(i);
241: if (obj instanceof SignatureAttr) {
242: return (SignatureAttr) obj;
243: }
244: }
245: return null;
246: }
247:
248: /**
249: * Set the constant value for this field as an int.
250: */
251: public void setConstantValue(int value) {
252: addAttribute(new ConstantValueAttr(mCp, mCp
253: .addConstantInteger(value)));
254: }
255:
256: /**
257: * Set the constant value for this field as a float.
258: */
259: public void setConstantValue(float value) {
260: addAttribute(new ConstantValueAttr(mCp, mCp
261: .addConstantFloat(value)));
262: }
263:
264: /**
265: * Set the constant value for this field as a long.
266: */
267: public void setConstantValue(long value) {
268: addAttribute(new ConstantValueAttr(mCp, mCp
269: .addConstantLong(value)));
270: }
271:
272: /**
273: * Set the constant value for this field as a double.
274: */
275: public void setConstantValue(double value) {
276: addAttribute(new ConstantValueAttr(mCp, mCp
277: .addConstantDouble(value)));
278: }
279:
280: /**
281: * Set the constant value for this field as a string.
282: */
283: public void setConstantValue(String value) {
284: addAttribute(new ConstantValueAttr(mCp, mCp
285: .addConstantString(value)));
286: }
287:
288: /**
289: * Mark this field as being synthetic by adding a special attribute.
290: */
291: public void markSynthetic() {
292: addAttribute(new SyntheticAttr(mCp));
293: }
294:
295: /**
296: * Mark this field as being deprecated by adding a special attribute.
297: */
298: public void markDeprecated() {
299: addAttribute(new DeprecatedAttr(mCp));
300: }
301:
302: public void addAttribute(Attribute attr) {
303: if (attr instanceof ConstantValueAttr) {
304: if (mConstant != null) {
305: mAttributes.remove(mConstant);
306: }
307: mConstant = (ConstantValueAttr) attr;
308: }
309:
310: mAttributes.add(attr);
311: }
312:
313: public Attribute[] getAttributes() {
314: Attribute[] attrs = new Attribute[mAttributes.size()];
315: return (Attribute[]) mAttributes.toArray(attrs);
316: }
317:
318: /**
319: * Returns the length (in bytes) of this object in the class file.
320: */
321: public int getLength() {
322: int length = 8;
323:
324: int size = mAttributes.size();
325: for (int i = 0; i < size; i++) {
326: length += ((Attribute) mAttributes.get(i)).getLength();
327: }
328:
329: return length;
330: }
331:
332: public void writeTo(DataOutput dout) throws IOException {
333: dout.writeShort(mModifiers.getBitmask());
334: dout.writeShort(mNameConstant.getIndex());
335: dout.writeShort(mDescriptorConstant.getIndex());
336:
337: int size = mAttributes.size();
338: dout.writeShort(size);
339: for (int i = 0; i < size; i++) {
340: Attribute attr = (Attribute) mAttributes.get(i);
341: attr.writeTo(dout);
342: }
343: }
344:
345: public String toString() {
346: String modStr = mModifiers.toString();
347: String typeStr;
348: if (modStr.length() == 0) {
349: return mType.getFullName() + ' ' + getName();
350: } else {
351: return modStr + ' ' + mType.getFullName() + ' ' + getName();
352: }
353: }
354:
355: static FieldInfo readFrom(ClassFile parent, DataInput din,
356: AttributeFactory attrFactory) throws IOException {
357: ConstantPool cp = parent.getConstantPool();
358:
359: int modifier = din.readUnsignedShort();
360: int index = din.readUnsignedShort();
361: ConstantUTFInfo nameConstant = (ConstantUTFInfo) cp
362: .getConstant(index);
363: index = din.readUnsignedShort();
364: ConstantUTFInfo descConstant = (ConstantUTFInfo) cp
365: .getConstant(index);
366:
367: FieldInfo info = new FieldInfo(parent, modifier, nameConstant,
368: descConstant);
369:
370: // Read attributes.
371: int size = din.readUnsignedShort();
372: for (int i = 0; i < size; i++) {
373: info.addAttribute(Attribute.readFrom(cp, din, attrFactory));
374: }
375:
376: return info;
377: }
378: }
|