Source for java.io.ObjectStreamField

   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: }