Frames | No Frames |
1: /* ObjectStreamField.java -- Class used to store name and class of fields 2: Copyright (C) 1998, 1999, 2003, 2004, 2005 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: * @author Tom Tromey (tromey@redhat.com) 53: * @author Jeroen Frijters (jeroen@frijters.net) 54: * @author Guilhem Lavaux (guilhem@kaffe.org) 55: * @author Michael Koch (konqueror@gmx.de) 56: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 57: */ 58: public class ObjectStreamField 59: implements Comparable<Object> 60: { 61: private String name; 62: private Class<?> type; 63: private String typename; 64: private int offset = -1; // XXX make sure this is correct 65: private boolean unshared; 66: private boolean persistent = false; 67: private boolean toset = true; 68: Field field; 69: 70: ObjectStreamField (Field field) 71: { 72: this (field.getName(), field.getType()); 73: this.field = field; 74: } 75: 76: /** 77: * This constructor creates an ObjectStreamField instance 78: * which represents a field named <code>name</code> and is 79: * of the type <code>type</code>. 80: * 81: * @param name Name of the field to export. 82: * @param type Type of the field in the concerned class. 83: */ 84: public ObjectStreamField (String name, Class<?> type) 85: { 86: this (name, type, false); 87: } 88: 89: /** 90: * This constructor creates an ObjectStreamField instance 91: * which represents a field named <code>name</code> and is 92: * of the type <code>type</code>. 93: * 94: * @param name Name of the field to export. 95: * @param type Type of the field in the concerned class. 96: * @param unshared true if field will be unshared, false otherwise. 97: */ 98: public ObjectStreamField (String name, Class<?> type, boolean unshared) 99: { 100: if (name == null) 101: throw new NullPointerException(); 102: 103: this.name = name; 104: this.type = type; 105: this.typename = TypeSignature.getEncodingOfClass(type); 106: this.unshared = unshared; 107: } 108: 109: /** 110: * There are many cases you can not get java.lang.Class from typename 111: * if your context class loader cannot load it, then use typename to 112: * construct the field. 113: * 114: * @param name Name of the field to export. 115: * @param typename The coded name of the type for this field. 116: */ 117: ObjectStreamField (String name, String typename) 118: { 119: this.name = name; 120: this.typename = typename; 121: } 122: 123: void resolveType(ClassLoader loader) 124: { 125: try 126: { 127: type = TypeSignature.getClassForEncoding(typename, true, loader); 128: } 129: catch(ClassNotFoundException e) 130: { 131: } 132: } 133: 134: /** 135: * This method returns the name of the field represented by the 136: * ObjectStreamField instance. 137: * 138: * @return A string containing the name of the field. 139: */ 140: public String getName () 141: { 142: return name; 143: } 144: 145: /** 146: * This method returns the class representing the type of the 147: * field which is represented by this instance of ObjectStreamField. 148: * 149: * @return A class representing the type of the field. 150: */ 151: public Class<?> getType () 152: { 153: return type; 154: } 155: 156: /** 157: * This method returns the char encoded type of the field which 158: * is represented by this instance of ObjectStreamField. 159: * 160: * @return A char representing the type of the field. 161: */ 162: public char getTypeCode () 163: { 164: return typename.charAt (0); 165: } 166: 167: /** 168: * This method returns a more explicit type name than 169: * {@link #getTypeCode()} in the case the type is a real 170: * class (and not a primitive). 171: * 172: * @return The name of the type (class name) if it is not a 173: * primitive, in the other case null is returned. 174: */ 175: public String getTypeString () 176: { 177: // use intern() 178: if (isPrimitive()) 179: return null; 180: return typename.intern(); 181: } 182: 183: /** 184: * This method returns the current offset of the field in 185: * the serialization stream relatively to the other fields. 186: * The offset is expressed in bytes. 187: * 188: * @return The offset of the field in bytes. 189: * @see #setOffset(int) 190: */ 191: public int getOffset () 192: { 193: return offset; 194: } 195: 196: /** 197: * This method sets the current offset of the field. 198: * 199: * @param off The offset of the field in bytes. 200: * @see #getOffset() 201: */ 202: protected void setOffset (int off) 203: { 204: offset = off; 205: } 206: 207: /** 208: * This method returns whether the field represented by this object is 209: * unshared or not. 210: * 211: * @return Tells if this field is unshared or not. 212: */ 213: public boolean isUnshared () 214: { 215: return unshared; 216: } 217: 218: /** 219: * This method returns true if the type of the field 220: * represented by this instance is a primitive. 221: * 222: * @return true if the type is a primitive, false 223: * in the other case. 224: */ 225: public boolean isPrimitive () 226: { 227: return typename.length() == 1; 228: } 229: 230: /** 231: * Compares this object to the given object. 232: * 233: * @param obj the object to compare to. 234: * 235: * @return -1, 0 or 1. 236: */ 237: public int compareTo (Object obj) 238: { 239: ObjectStreamField f = (ObjectStreamField) obj; 240: boolean this_is_primitive = isPrimitive (); 241: boolean f_is_primitive = f.isPrimitive (); 242: 243: if (this_is_primitive && !f_is_primitive) 244: return -1; 245: 246: if (!this_is_primitive && f_is_primitive) 247: return 1; 248: 249: return getName ().compareTo (f.getName ()); 250: } 251: 252: /** 253: * This method is specific to classpath's implementation and so has the default 254: * access. It changes the state of this field to "persistent". It means that 255: * the field should not be changed when the stream is read (if it is not 256: * explicitly specified using serialPersistentFields). 257: * 258: * @param persistent True if the field is persistent, false in the 259: * other cases. 260: * @see #isPersistent() 261: */ 262: void setPersistent(boolean persistent) 263: { 264: this.persistent = persistent; 265: } 266: 267: /** 268: * This method returns true if the field is marked as persistent. 269: * 270: * @return True if persistent, false in the other cases. 271: * @see #setPersistent(boolean) 272: */ 273: boolean isPersistent() 274: { 275: return persistent; 276: } 277: 278: /** 279: * This method is specific to classpath's implementation and so 280: * has the default access. It changes the state of this field as 281: * to be set by ObjectInputStream. 282: * 283: * @param toset True if this field should be set, false in the other 284: * cases. 285: * @see #isToSet() 286: */ 287: void setToSet(boolean toset) 288: { 289: this.toset = toset; 290: } 291: 292: /** 293: * This method returns true if the field is marked as to be 294: * set. 295: * 296: * @return True if it is to be set, false in the other cases. 297: * @see #setToSet(boolean) 298: */ 299: boolean isToSet() 300: { 301: return toset; 302: } 303: 304: /** 305: * This method searches for its field reference in the specified class 306: * object. It requests privileges. If an error occurs the internal field 307: * reference is not modified. 308: * 309: * @throws NoSuchFieldException if the field name does not exist in this class. 310: * @throws SecurityException if there was an error requesting the privileges. 311: */ 312: void lookupField(Class clazz) throws NoSuchFieldException, SecurityException 313: { 314: final Field f = clazz.getDeclaredField(name); 315: 316: AccessController.doPrivileged(new PrivilegedAction() 317: { 318: public Object run() 319: { 320: f.setAccessible(true); 321: return null; 322: } 323: }); 324: 325: this.field = f; 326: } 327: 328: /** 329: * This method check whether the field described by this 330: * instance of ObjectStreamField is compatible with the 331: * actual implementation of this field. 332: * 333: * @throws NullPointerException if this field does not exist 334: * in the real class. 335: * @throws InvalidClassException if the types are incompatible. 336: */ 337: void checkFieldType() throws InvalidClassException 338: { 339: Class<?> ftype = field.getType(); 340: 341: if (!ftype.isAssignableFrom(type)) 342: throw new InvalidClassException 343: ("invalid field type for " + name + 344: " in class " + field.getDeclaringClass()); 345: } 346: 347: /** 348: * Returns a string representing this object. 349: * 350: * @return the string. 351: */ 352: public String toString () 353: { 354: return "ObjectStreamField< " + type + " " + name + " >"; 355: } 356: 357: final void setBooleanField(Object obj, boolean val) 358: { 359: VMObjectStreamClass.setBooleanNative(field, obj, val); 360: } 361: 362: final void setByteField(Object obj, byte val) 363: { 364: VMObjectStreamClass.setByteNative(field, obj, val); 365: } 366: 367: final void setCharField(Object obj, char val) 368: { 369: VMObjectStreamClass.setCharNative(field, obj, val); 370: } 371: 372: final void setShortField(Object obj, short val) 373: { 374: VMObjectStreamClass.setShortNative(field, obj, val); 375: } 376: 377: final void setIntField(Object obj, int val) 378: { 379: VMObjectStreamClass.setIntNative(field, obj, val); 380: } 381: 382: final void setLongField(Object obj, long val) 383: { 384: VMObjectStreamClass.setLongNative(field, obj, val); 385: } 386: 387: final void setFloatField(Object obj, float val) 388: { 389: VMObjectStreamClass.setFloatNative(field, obj, val); 390: } 391: 392: final void setDoubleField(Object obj, double val) 393: { 394: VMObjectStreamClass.setDoubleNative(field, obj, val); 395: } 396: 397: final void setObjectField(Object obj, Object val) 398: { 399: VMObjectStreamClass.setObjectNative(field, obj, val); 400: } 401: }