Frames | No Frames |
1: /* ObjectStreamField.java -- Class used to store name and class of fields 2: Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.io; 40: 41: import gnu.java.lang.reflect.TypeSignature; 42: 43: import java.lang.reflect.Field; 44: import java.security.AccessController; 45: import java.security.PrivilegedAction; 46: 47: /** 48: * This class intends to describe the field of a class for the serialization 49: * subsystem. Serializable fields in a serializable class can be explicitly 50: * exported using an array of ObjectStreamFields. 51: */ 52: public class ObjectStreamField implements Comparable 53: { 54: private String name; 55: private Class type; 56: private String typename; 57: private int offset = -1; // XXX make sure this is correct 58: private boolean unshared; 59: private boolean persistent = false; 60: private boolean toset = true; 61: private Field field; 62: 63: ObjectStreamField (Field field) 64: { 65: this (field.getName(), field.getType()); 66: this.field = field; 67: } 68: 69: /** 70: * This constructor creates an ObjectStreamField instance 71: * which represents a field named <code>name</code> and is 72: * of the type <code>type</code>. 73: * 74: * @param name Name of the field to export. 75: * @param type Type of the field in the concerned class. 76: */ 77: public ObjectStreamField (String name, Class type) 78: { 79: this (name, type, false); 80: } 81: 82: /** 83: * This constructor creates an ObjectStreamField instance 84: * which represents a field named <code>name</code> and is 85: * of the type <code>type</code>. 86: * 87: * @param name Name of the field to export. 88: * @param type Type of the field in the concerned class. 89: * @param unshared true if field will be unshared, false otherwise. 90: */ 91: public ObjectStreamField (String name, Class type, boolean unshared) 92: { 93: if (name == null) 94: throw new NullPointerException(); 95: 96: this.name = name; 97: this.type = type; 98: this.typename = TypeSignature.getEncodingOfClass(type); 99: this.unshared = unshared; 100: } 101: 102: /** 103: * There are many cases you can not get java.lang.Class from typename 104: * if your context class loader cannot load it, then use typename to 105: * construct the field. 106: * 107: * @param name Name of the field to export. 108: * @param typename The coded name of the type for this field. 109: */ 110: ObjectStreamField (String name, String typename) 111: { 112: this.name = name; 113: this.typename = typename; 114: try 115: { 116: type = TypeSignature.getClassForEncoding(typename); 117: } 118: catch(ClassNotFoundException e) 119: { 120: } 121: } 122: 123: /** 124: * There are many cases you can not get java.lang.Class from typename 125: * if your context class loader cann not load it, then use typename to 126: * construct the field. 127: * 128: * @param name Name of the field to export. 129: * @param typename The coded name of the type for this field. 130: * @param loader The class loader to use to resolve class names. 131: */ 132: ObjectStreamField (String name, String typename, ClassLoader loader) 133: { 134: this.name = name; 135: this.typename = typename; 136: try 137: { 138: type = TypeSignature.getClassForEncoding(typename, true, loader); 139: } 140: catch(ClassNotFoundException e) 141: { 142: } 143: } 144: 145: /** 146: * This method returns the name of the field represented by the 147: * ObjectStreamField instance. 148: * 149: * @return A string containing the name of the field. 150: */ 151: public String getName () 152: { 153: return name; 154: } 155: 156: /** 157: * This method returns the class representing the type of the 158: * field which is represented by this instance of ObjectStreamField. 159: * 160: * @return A class representing the type of the field. 161: */ 162: public Class getType () 163: { 164: return type; 165: } 166: 167: /** 168: * This method returns the char encoded type of the field which 169: * is represented by this instance of ObjectStreamField. 170: * 171: * @return A char representing the type of the field. 172: */ 173: public char getTypeCode () 174: { 175: return typename.charAt (0); 176: } 177: 178: /** 179: * This method returns a more explicit type name than 180: * {@link #getTypeCode()} in the case the type is a real 181: * class (and not a primitive). 182: * 183: * @return The name of the type (class name) if it is not a 184: * primitive, in the other case null is returned. 185: */ 186: public String getTypeString () 187: { 188: // use intern() 189: if (isPrimitive()) 190: return null; 191: return typename.intern(); 192: } 193: 194: /** 195: * This method returns the current offset of the field in 196: * the serialization stream relatively to the other fields. 197: * The offset is expressed in bytes. 198: * 199: * @return The offset of the field in bytes. 200: * @see #setOffset(int) 201: */ 202: public int getOffset () 203: { 204: return offset; 205: } 206: 207: /** 208: * This method sets the current offset of the field. 209: * 210: * @param off The offset of the field in bytes. 211: * @see #getOffset() 212: */ 213: protected void setOffset (int off) 214: { 215: offset = off; 216: } 217: 218: /** 219: * This method returns whether the field represented by this object is 220: * unshared or not. 221: * 222: * @return Tells if this field is unshared or not. 223: */ 224: public boolean isUnshared () 225: { 226: return unshared; 227: } 228: 229: /** 230: * This method returns true if the type of the field 231: * represented by this instance is a primitive. 232: * 233: * @return true if the type is a primitive, false 234: * in the other case. 235: */ 236: public boolean isPrimitive () 237: { 238: return typename.length() == 1; 239: } 240: 241: /** 242: * Compares this object to the given object. 243: * 244: * @param obj the object to compare to. 245: * 246: * @return -1, 0 or 1. 247: */ 248: public int compareTo (Object obj) 249: { 250: ObjectStreamField f = (ObjectStreamField) obj; 251: boolean this_is_primitive = isPrimitive (); 252: boolean f_is_primitive = f.isPrimitive (); 253: 254: if (this_is_primitive && !f_is_primitive) 255: return -1; 256: 257: if (!this_is_primitive && f_is_primitive) 258: return 1; 259: 260: return getName ().compareTo (f.getName ()); 261: } 262: 263: /** 264: * This method is specific to classpath's implementation and so has the default 265: * access. It changes the state of this field to "persistent". It means that 266: * the field should not be changed when the stream is read (if it is not 267: * explicitly specified using serialPersistentFields). 268: * 269: * @param persistent True if the field is persistent, false in the 270: * other cases. 271: * @see #isPersistent() 272: */ 273: void setPersistent(boolean persistent) 274: { 275: this.persistent = persistent; 276: } 277: 278: /** 279: * This method returns true if the field is marked as persistent. 280: * 281: * @return True if persistent, false in the other cases. 282: * @see #setPersistent(boolean) 283: */ 284: boolean isPersistent() 285: { 286: return persistent; 287: } 288: 289: /** 290: * This method is specific to classpath's implementation and so 291: * has the default access. It changes the state of this field as 292: * to be set by ObjectInputStream. 293: * 294: * @param toset True if this field should be set, false in the other 295: * cases. 296: * @see #isToSet() 297: */ 298: void setToSet(boolean toset) 299: { 300: this.toset = toset; 301: } 302: 303: /** 304: * This method returns true if the field is marked as to be 305: * set. 306: * 307: * @return True if it is to be set, false in the other cases. 308: * @see #setToSet(boolean) 309: */ 310: boolean isToSet() 311: { 312: return toset; 313: } 314: 315: /** 316: * This method searches for its field reference in the specified class 317: * object. It requests privileges. If an error occurs the internal field 318: * reference is not modified. 319: * 320: * @throws NoSuchFieldException if the field name does not exist in this class. 321: * @throws SecurityException if there was an error requesting the privileges. 322: */ 323: void lookupField(Class clazz) throws NoSuchFieldException, SecurityException 324: { 325: final Field f = clazz.getDeclaredField(name); 326: 327: AccessController.doPrivileged(new PrivilegedAction() 328: { 329: public Object run() 330: { 331: f.setAccessible(true); 332: return null; 333: } 334: }); 335: 336: this.field = f; 337: } 338: 339: /** 340: * This method check whether the field described by this 341: * instance of ObjectStreamField is compatible with the 342: * actual implementation of this field. 343: * 344: * @throws NullPointerException if this field does not exist 345: * in the real class. 346: * @throws InvalidClassException if the types are incompatible. 347: */ 348: void checkFieldType() throws InvalidClassException 349: { 350: Class ftype = field.getType(); 351: 352: if (!ftype.isAssignableFrom(type)) 353: throw new InvalidClassException 354: ("invalid field type for " + name + 355: " in class " + field.getDeclaringClass()); 356: } 357: 358: /** 359: * Returns a string representing this object. 360: * 361: * @return the string. 362: */ 363: public String toString () 364: { 365: return "ObjectStreamField< " + type + " " + name + " >"; 366: } 367: 368: final void setBooleanField(Object obj, boolean val) 369: { 370: VMObjectStreamClass.setBooleanNative(field, obj, val); 371: } 372: 373: final void setByteField(Object obj, byte val) 374: { 375: VMObjectStreamClass.setByteNative(field, obj, val); 376: } 377: 378: final void setCharField(Object obj, char val) 379: { 380: VMObjectStreamClass.setCharNative(field, obj, val); 381: } 382: 383: final void setShortField(Object obj, short val) 384: { 385: VMObjectStreamClass.setShortNative(field, obj, val); 386: } 387: 388: final void setIntField(Object obj, int val) 389: { 390: VMObjectStreamClass.setIntNative(field, obj, val); 391: } 392: 393: final void setLongField(Object obj, long val) 394: { 395: VMObjectStreamClass.setLongNative(field, obj, val); 396: } 397: 398: final void setFloatField(Object obj, float val) 399: { 400: VMObjectStreamClass.setFloatNative(field, obj, val); 401: } 402: 403: final void setDoubleField(Object obj, double val) 404: { 405: VMObjectStreamClass.setDoubleNative(field, obj, val); 406: } 407: 408: final void setObjectField(Object obj, Object val) 409: { 410: VMObjectStreamClass.setObjectNative(field, obj, val); 411: } 412: }