001: /*
002: * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.io;
027:
028: import java.lang.reflect.Field;
029:
030: /**
031: * A description of a Serializable field from a Serializable class. An array
032: * of ObjectStreamFields is used to declare the Serializable fields of a class.
033: *
034: * @author Mike Warres
035: * @author Roger Riggs
036: * @version 1.53, 07/05/05
037: * @see ObjectStreamClass
038: * @since 1.2
039: */
040: public class ObjectStreamField implements Comparable<Object> {
041:
042: /** field name */
043: private final String name;
044: /** canonical JVM signature of field type */
045: private final String signature;
046: /** field type (Object.class if unknown non-primitive type) */
047: private final Class type;
048: /** whether or not to (de)serialize field values as unshared */
049: private final boolean unshared;
050: /** corresponding reflective field object, if any */
051: private final Field field;
052: /** offset of field value in enclosing field group */
053: private int offset = 0;
054:
055: /**
056: * Create a Serializable field with the specified type. This field should
057: * be documented with a <code>serialField</code> tag.
058: *
059: * @param name the name of the serializable field
060: * @param type the <code>Class</code> object of the serializable field
061: */
062: public ObjectStreamField(String name, Class<?> type) {
063: this (name, type, false);
064: }
065:
066: /**
067: * Creates an ObjectStreamField representing a serializable field with the
068: * given name and type. If unshared is false, values of the represented
069: * field are serialized and deserialized in the default manner--if the
070: * field is non-primitive, object values are serialized and deserialized as
071: * if they had been written and read by calls to writeObject and
072: * readObject. If unshared is true, values of the represented field are
073: * serialized and deserialized as if they had been written and read by
074: * calls to writeUnshared and readUnshared.
075: *
076: * @param name field name
077: * @param type field type
078: * @param unshared if false, write/read field values in the same manner
079: * as writeObject/readObject; if true, write/read in the same
080: * manner as writeUnshared/readUnshared
081: * @since 1.4
082: */
083: public ObjectStreamField(String name, Class<?> type,
084: boolean unshared) {
085: if (name == null) {
086: throw new NullPointerException();
087: }
088: this .name = name;
089: this .type = type;
090: this .unshared = unshared;
091: signature = ObjectStreamClass.getClassSignature(type).intern();
092: field = null;
093: }
094:
095: /**
096: * Creates an ObjectStreamField representing a field with the given name,
097: * signature and unshared setting.
098: */
099: ObjectStreamField(String name, String signature, boolean unshared) {
100: if (name == null) {
101: throw new NullPointerException();
102: }
103: this .name = name;
104: this .signature = signature.intern();
105: this .unshared = unshared;
106: field = null;
107:
108: switch (signature.charAt(0)) {
109: case 'Z':
110: type = Boolean.TYPE;
111: break;
112: case 'B':
113: type = Byte.TYPE;
114: break;
115: case 'C':
116: type = Character.TYPE;
117: break;
118: case 'S':
119: type = Short.TYPE;
120: break;
121: case 'I':
122: type = Integer.TYPE;
123: break;
124: case 'J':
125: type = Long.TYPE;
126: break;
127: case 'F':
128: type = Float.TYPE;
129: break;
130: case 'D':
131: type = Double.TYPE;
132: break;
133: case 'L':
134: case '[':
135: type = Object.class;
136: break;
137: default:
138: throw new IllegalArgumentException("illegal signature");
139: }
140: }
141:
142: /**
143: * Creates an ObjectStreamField representing the given field with the
144: * specified unshared setting. For compatibility with the behavior of
145: * earlier serialization implementations, a "showType" parameter is
146: * necessary to govern whether or not a getType() call on this
147: * ObjectStreamField (if non-primitive) will return Object.class (as
148: * opposed to a more specific reference type).
149: */
150: ObjectStreamField(Field field, boolean unshared, boolean showType) {
151: this .field = field;
152: this .unshared = unshared;
153: name = field.getName();
154: Class ftype = field.getType();
155: type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
156: signature = ObjectStreamClass.getClassSignature(ftype).intern();
157: }
158:
159: /**
160: * Get the name of this field.
161: *
162: * @return a <code>String</code> representing the name of the serializable
163: * field
164: */
165: public String getName() {
166: return name;
167: }
168:
169: /**
170: * Get the type of the field. If the type is non-primitive and this
171: * <code>ObjectStreamField</code> was obtained from a deserialized {@link
172: * ObjectStreamClass} instance, then <code>Object.class</code> is returned.
173: * Otherwise, the <code>Class</code> object for the type of the field is
174: * returned.
175: *
176: * @return a <code>Class</code> object representing the type of the
177: * serializable field
178: */
179: public Class<?> getType() {
180: return type;
181: }
182:
183: /**
184: * Returns character encoding of field type. The encoding is as follows:
185: * <blockquote><pre>
186: * B byte
187: * C char
188: * D double
189: * F float
190: * I int
191: * J long
192: * L class or interface
193: * S short
194: * Z boolean
195: * [ array
196: * </pre></blockquote>
197: *
198: * @return the typecode of the serializable field
199: */
200: // REMIND: deprecate?
201: public char getTypeCode() {
202: return signature.charAt(0);
203: }
204:
205: /**
206: * Return the JVM type signature.
207: *
208: * @return null if this field has a primitive type.
209: */
210: // REMIND: deprecate?
211: public String getTypeString() {
212: return isPrimitive() ? null : signature;
213: }
214:
215: /**
216: * Offset of field within instance data.
217: *
218: * @return the offset of this field
219: * @see #setOffset
220: */
221: // REMIND: deprecate?
222: public int getOffset() {
223: return offset;
224: }
225:
226: /**
227: * Offset within instance data.
228: *
229: * @param offset the offset of the field
230: * @see #getOffset
231: */
232: // REMIND: deprecate?
233: protected void setOffset(int offset) {
234: this .offset = offset;
235: }
236:
237: /**
238: * Return true if this field has a primitive type.
239: *
240: * @return true if and only if this field corresponds to a primitive type
241: */
242: // REMIND: deprecate?
243: public boolean isPrimitive() {
244: char tcode = signature.charAt(0);
245: return ((tcode != 'L') && (tcode != '['));
246: }
247:
248: /**
249: * Returns boolean value indicating whether or not the serializable field
250: * represented by this ObjectStreamField instance is unshared.
251: *
252: * @since 1.4
253: */
254: public boolean isUnshared() {
255: return unshared;
256: }
257:
258: /**
259: * Compare this field with another <code>ObjectStreamField</code>. Return
260: * -1 if this is smaller, 0 if equal, 1 if greater. Types that are
261: * primitives are "smaller" than object types. If equal, the field names
262: * are compared.
263: */
264: // REMIND: deprecate?
265: public int compareTo(Object obj) {
266: ObjectStreamField other = (ObjectStreamField) obj;
267: boolean isPrim = isPrimitive();
268: if (isPrim != other.isPrimitive()) {
269: return isPrim ? -1 : 1;
270: }
271: return name.compareTo(other.name);
272: }
273:
274: /**
275: * Return a string that describes this field.
276: */
277: public String toString() {
278: return signature + ' ' + name;
279: }
280:
281: /**
282: * Returns field represented by this ObjectStreamField, or null if
283: * ObjectStreamField is not associated with an actual field.
284: */
285: Field getField() {
286: return field;
287: }
288:
289: /**
290: * Returns JVM type signature of field (similar to getTypeString, except
291: * that signature strings are returned for primitive fields as well).
292: */
293: String getSignature() {
294: return signature;
295: }
296: }
|