001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package EDU.purdue.cs.bloat.file;
022:
023: import java.io.*;
024:
025: import EDU.purdue.cs.bloat.reflect.*;
026:
027: /**
028: * Field models a field (member variable) in a class. The Field class grants
029: * access to information such as the field's modifiers, its name and type
030: * descriptor (represented as indices into the constant pool), and any
031: * attributes of the field. Static fields have a ConstantValue attribute.
032: *
033: * @see ConstantValue
034: *
035: * @author Nate Nystrom (<a
036: * href="mailto:nystrom@cs.purdue.edu">nystrom@cs.purdue.edu</a>)
037: */
038: public class Field implements FieldInfo {
039: private ClassInfo classInfo;
040:
041: private int modifiers;
042:
043: private int name;
044:
045: private int type;
046:
047: private Attribute[] attrs;
048:
049: private ConstantValue constantValue;
050:
051: /**
052: * Constructor for creating a new field from scratch
053: */
054: Field(final ClassInfo classInfo, final int modifiers,
055: final int typeIndex, final int nameIndex) {
056: this .classInfo = classInfo;
057: this .modifiers = modifiers;
058: this .name = nameIndex;
059: this .type = typeIndex;
060: this .attrs = new Attribute[0];
061: this .constantValue = null;
062: }
063:
064: /**
065: * Constructor for creating a new field that has a constant value from
066: * scratch
067: */
068: Field(final ClassInfo classInfo, final int modifiers,
069: final int typeIndex, final int nameIndex,
070: final int cvNameIndex, final int constantValueIndex) {
071: this .classInfo = classInfo;
072: this .modifiers = modifiers;
073: this .name = nameIndex;
074: this .type = typeIndex;
075: this .constantValue = new ConstantValue(cvNameIndex, 2,
076: constantValueIndex);
077:
078: // The constant value is an attribute
079: this .attrs = new Attribute[1];
080: this .attrs[0] = constantValue;
081: }
082:
083: /**
084: * Constructor. Read a field from a class file.
085: *
086: * @param in
087: * The data stream of the class file.
088: * @param classInfo
089: * The class file containing the field.
090: * @exception IOException
091: * If an error occurs while reading.
092: */
093: public Field(final DataInputStream in, final ClassInfo classInfo)
094: throws IOException {
095: this .classInfo = classInfo;
096:
097: modifiers = in.readUnsignedShort();
098:
099: name = in.readUnsignedShort();
100: type = in.readUnsignedShort();
101:
102: final int numAttributes = in.readUnsignedShort();
103:
104: attrs = new Attribute[numAttributes];
105:
106: for (int i = 0; i < numAttributes; i++) {
107: final int nameIndex = in.readUnsignedShort();
108: final int length = in.readInt();
109:
110: final Constant name = classInfo.constants()[nameIndex];
111:
112: if (name != null) {
113: if ("ConstantValue".equals(name.value())) {
114: constantValue = new ConstantValue(in, nameIndex,
115: length);
116: attrs[i] = constantValue;
117: }
118: }
119:
120: if (attrs[i] == null) {
121: attrs[i] = new GenericAttribute(in, nameIndex, length);
122: }
123: }
124: }
125:
126: /**
127: * Get the class which declared the field.
128: *
129: * @return The ClassInfo of the class which declared the field.
130: */
131: public ClassInfo declaringClass() {
132: return classInfo;
133: }
134:
135: /**
136: * Set the index into the constant pool of the name of the field.
137: *
138: * @param name
139: * The name of the field.
140: */
141: public void setNameIndex(final int name) {
142: this .name = name;
143: }
144:
145: /**
146: * Set the index into the constant pool of the type of the field.
147: *
148: * @param type
149: * The type of the field.
150: */
151: public void setTypeIndex(final int type) {
152: this .type = type;
153: }
154:
155: /**
156: * Get the index into the constant pool of the name of the field.
157: *
158: * @return The index into the constant pool of the name of the field.
159: */
160: public int nameIndex() {
161: return name;
162: }
163:
164: /**
165: * Get the index into the constant pool of the type of the field.
166: *
167: * @return The index into the constant pool of the type of the field.
168: */
169: public int typeIndex() {
170: return type;
171: }
172:
173: /**
174: * Set the modifiers of the field. The values correspond to the constants in
175: * the Modifiers class.
176: *
177: * @param modifiers
178: * A bit vector of modifier flags for the field.
179: * @see Modifiers
180: */
181: public void setModifiers(final int modifiers) {
182: this .modifiers = modifiers;
183: }
184:
185: /**
186: * Get the modifiers of the field. The values correspond to the constants in
187: * the Modifiers class.
188: *
189: * @return A bit vector of modifier flags for the field.
190: * @see Modifiers
191: */
192: public int modifiers() {
193: return modifiers;
194: }
195:
196: /**
197: * Get the index into the constant pool of the field's constant value, if
198: * any. Returns 0 if the field does not have a constant value.
199: *
200: * @see ClassInfo#constants
201: */
202: public int constantValue() {
203: if (constantValue != null) {
204: return constantValue.constantValueIndex();
205: }
206: return 0;
207: }
208:
209: /**
210: * Set the index into the constant pool of the field's constant value.
211: *
212: * @see ClassInfo#constants
213: */
214: public void setConstantValue(final int index) {
215: if (constantValue != null) {
216: constantValue.setConstantValueIndex(index);
217: }
218: }
219:
220: /**
221: * Write the field to a class file.
222: *
223: * @param out
224: * The data stream of the class file.
225: * @exception IOException
226: * If an error occurs while writing.
227: */
228: public void write(final DataOutputStream out) throws IOException {
229: out.writeShort(modifiers);
230:
231: out.writeShort(name);
232: out.writeShort(type);
233:
234: out.writeShort(attrs.length);
235:
236: for (int i = 0; i < attrs.length; i++) {
237: out.writeShort(attrs[i].nameIndex());
238: out.writeInt(attrs[i].length());
239: attrs[i].writeData(out);
240: }
241: }
242:
243: /**
244: * Convert the field to a string.
245: *
246: * @return A string representation of the field.
247: */
248: public String toString() {
249: String x = "";
250:
251: x += " (modifiers";
252:
253: if ((modifiers & Modifiers.PUBLIC) != 0) {
254: x += " PUBLIC";
255: }
256: if ((modifiers & Modifiers.PRIVATE) != 0) {
257: x += " PRIVATE";
258: }
259: if ((modifiers & Modifiers.PROTECTED) != 0) {
260: x += " PROTECTED";
261: }
262: if ((modifiers & Modifiers.STATIC) != 0) {
263: x += " STATIC";
264: }
265: if ((modifiers & Modifiers.FINAL) != 0) {
266: x += " FINAL";
267: }
268: if ((modifiers & Modifiers.SYNCHRONIZED) != 0) {
269: x += " SYNCHRONIZED";
270: }
271: if ((modifiers & Modifiers.VOLATILE) != 0) {
272: x += " VOLATILE";
273: }
274: if ((modifiers & Modifiers.TRANSIENT) != 0) {
275: x += " TRANSIENT";
276: }
277: if ((modifiers & Modifiers.NATIVE) != 0) {
278: x += " NATIVE";
279: }
280: if ((modifiers & Modifiers.INTERFACE) != 0) {
281: x += " INTERFACE";
282: }
283: if ((modifiers & Modifiers.ABSTRACT) != 0) {
284: x += " ABSTRACT";
285: }
286: x += ")";
287:
288: if (constantValue != null) {
289: x += " " + constantValue;
290: }
291:
292: return "(field " + name + " " + type + x + ")";
293: }
294: }
|