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