1. /*
  2. * @(#)ObjectStreamField.java 1.30 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.io;
  11. import java.lang.reflect.Field;
  12. /**
  13. * A description of a Serializable field from a Serializable class.
  14. * An array of ObjectStreamFields is used to declare the Serializable
  15. * fields of a class.
  16. *
  17. * @author Roger Riggs
  18. * @version 1.30, 02/02/00
  19. * @see ObjectStreamClass
  20. * @since 1.2
  21. */
  22. public class ObjectStreamField implements Comparable {
  23. /**
  24. * Create a Serializable field with the specified type.
  25. * This field should be documented with a <code>serialField</code>
  26. * tag.
  27. *
  28. * @param n the name of the serializable field
  29. * @param clazz the <code>Class</code> object of the serializable field
  30. */
  31. public ObjectStreamField(String n, Class clazz) {
  32. name = n;
  33. this.clazz = clazz;
  34. // Compute the typecode for easy switching
  35. if (clazz.isPrimitive()) {
  36. if (clazz == Integer.TYPE) {
  37. type = 'I';
  38. } else if (clazz == Byte.TYPE) {
  39. type = 'B';
  40. } else if (clazz == Long.TYPE) {
  41. type = 'J';
  42. } else if (clazz == Float.TYPE) {
  43. type = 'F';
  44. } else if (clazz == Double.TYPE) {
  45. type = 'D';
  46. } else if (clazz == Short.TYPE) {
  47. type = 'S';
  48. } else if (clazz == Character.TYPE) {
  49. type = 'C';
  50. } else if (clazz == Boolean.TYPE) {
  51. type = 'Z';
  52. }
  53. } else if (clazz.isArray()) {
  54. type = '[';
  55. typeString = ObjectStreamClass.getSignature(clazz).intern();
  56. } else {
  57. type = 'L';
  58. typeString = ObjectStreamClass.getSignature(clazz).intern();
  59. }
  60. }
  61. /**
  62. * Create a default Serializable field for <code>field</code>.
  63. */
  64. ObjectStreamField(Field field) {
  65. this(field.getName(), field.getType());
  66. this.field = field;
  67. }
  68. /**
  69. * Create an ObjectStreamField containing a reflected Field.
  70. */
  71. ObjectStreamField(String n, char t, Field f, String ts)
  72. {
  73. // System.out.println("new field, " + n + " " + t + " " + ts);
  74. name = n;
  75. type = t;
  76. field = f;
  77. typeString = (ts != null ? ts.intern() : null);
  78. }
  79. /**
  80. * SearchKey constructor.
  81. * @see #compareTo(Object)
  82. */
  83. private ObjectStreamField(String name, boolean isPrimitive) {
  84. // only set fields that compareTo uses for comparison.
  85. this.name = name;
  86. setSearchKeyTypeString(isPrimitive);
  87. }
  88. /**
  89. * Get the name of this field.
  90. *
  91. * @return a <code>String</code> representing the name of the serializable
  92. * field
  93. */
  94. public String getName() {
  95. return name;
  96. }
  97. /**
  98. * Get the type of the field.
  99. *
  100. * @return the <code>Class</code> object of the serializable field
  101. */
  102. public Class getType() {
  103. if (clazz != null)
  104. return clazz;
  105. switch (type) {
  106. case 'B': clazz = Byte.TYPE;
  107. break;
  108. case 'C': clazz = Character.TYPE;
  109. break;
  110. case 'S': clazz = Short.TYPE;
  111. break;
  112. case 'I': clazz = Integer.TYPE;
  113. break;
  114. case 'J': clazz = Long.TYPE;
  115. break;
  116. case 'F': clazz = Float.TYPE;
  117. break;
  118. case 'D': clazz = Double.TYPE;
  119. break;
  120. case 'Z': clazz = Boolean.TYPE;
  121. break;
  122. case '[':
  123. case 'L':
  124. clazz = Object.class;
  125. break;
  126. }
  127. return clazz;
  128. }
  129. /**
  130. * Returns character encoding of field type.
  131. * The encoding is as follows:
  132. * <blockquote><pre>
  133. * B byte
  134. * C char
  135. * D double
  136. * F float
  137. * I int
  138. * J long
  139. * L class or interface
  140. * S short
  141. * Z boolean
  142. * [ array
  143. * </pre></blockquote>
  144. *
  145. * @return the typecode of the serializable field
  146. */
  147. public char getTypeCode() {
  148. return type;
  149. }
  150. /**
  151. * Return the JVM type signature.
  152. *
  153. * @return null if this field has a primitive type.
  154. */
  155. public String getTypeString() {
  156. return typeString;
  157. }
  158. /**
  159. * Offset of field within instance data.
  160. *
  161. * @return the offset of this field
  162. * @see #setOffset
  163. */
  164. public int getOffset() {
  165. return bufoffset;
  166. }
  167. /**
  168. * Offset within instance data.
  169. *
  170. * @param offset the offset of the field
  171. * @see #getOffset
  172. */
  173. protected void setOffset(int offset) {
  174. bufoffset = offset;
  175. }
  176. /*
  177. * Default constructor creates an empty field.
  178. * Usually used just to get to the sort functions.
  179. */
  180. ObjectStreamField() {
  181. }
  182. /**
  183. * Return true if this field has a primitive type.
  184. *
  185. * @return true if and only if this field corresponds to a primitive type
  186. */
  187. public boolean isPrimitive() {
  188. return (type != '[' && type != 'L');
  189. }
  190. /**
  191. * Compare this field with another <code>ObjectStreamField</code>.
  192. * Return -1 if this is smaller, 0 if equal, 1 if greater.
  193. * Types that are primitives are "smaller" than object types.
  194. * If equal, the field names are compared.
  195. */
  196. public int compareTo(Object o) {
  197. ObjectStreamField f2 = (ObjectStreamField)o;
  198. boolean thisprim = (this.typeString == null);
  199. boolean otherprim = (f2.typeString == null);
  200. if (thisprim != otherprim) {
  201. return (thisprim ? -1 : 1);
  202. }
  203. return this.name.compareTo(f2.name);
  204. }
  205. /**
  206. * Return a string that describes this field.
  207. */
  208. public String toString() {
  209. if (typeString != null)
  210. return typeString + " " + name;
  211. else
  212. return type + " " + name;
  213. }
  214. /**
  215. * Compare the type of this ObjectStreamField with <code>other</code>.
  216. *
  217. * @return true if both ObjectStreamFields are serializable compatible.
  218. */
  219. boolean typeEquals(ObjectStreamField other) {
  220. if (other == null || type != other.type)
  221. return false;
  222. /* Optimization: Since interning typeString,
  223. * this short circuit can save some time.
  224. * Also, covers case where both typeStrings are null.
  225. */
  226. if (typeString == other.typeString)
  227. return true;
  228. else
  229. return ObjectStreamClass.compareClassNames(typeString,
  230. other.typeString,
  231. '/');
  232. }
  233. /*
  234. * Return a field.
  235. * @see java.lang.reflect.Field
  236. */
  237. Field getField() {
  238. return field;
  239. }
  240. void setField(Field field) {
  241. this.field = field;
  242. }
  243. /**
  244. * @return a ObjectStreamField with enough fields set to search
  245. * a list for a matching ObjectStreamField.
  246. * @see #compareTo(Object)
  247. */
  248. static ObjectStreamField constructSearchKey(String fieldName,
  249. Class fieldType)
  250. {
  251. return new ObjectStreamField(fieldName, fieldType.isPrimitive());
  252. }
  253. void setSearchKeyTypeString(boolean isPrimitive) {
  254. typeString = isPrimitive ? null : OBJECT_TYPESTRING;
  255. }
  256. private String name; // the name of the field
  257. private char type; // first byte of the type signature
  258. private Field field; // Reflected field.
  259. private String typeString; // iff object, fully qualified typename containing '/'
  260. private int bufoffset; // offset in the data buffer, or index in objects
  261. private Class clazz; // the type of this field, if has been resolved
  262. /* a string object used for ObjectStreamField search. For search purposes,
  263. * it is sufficient that this string is non-null.
  264. */
  265. private static final String OBJECT_TYPESTRING=new String("");
  266. };