/* ObjectStreamField.java -- Class used to store name and class of fields
   Copyright (C) 1998, 1999, 2003, 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.io;

import gnu.java.lang.reflect.TypeSignature;

import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * This class intends to describe the field of a class for the serialization
 * subsystem. Serializable fields in a serializable class can be explicitly
 * exported using an array of ObjectStreamFields.
 *
 * @author Tom Tromey (tromey@redhat.com)
 * @author Jeroen Frijters (jeroen@frijters.net)
 * @author Guilhem Lavaux (guilhem@kaffe.org)
 * @author Michael Koch (konqueror@gmx.de)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 */
public class ObjectStreamField
  implements Comparable<Object>
{
  private String name;
  private Class<?> type;
  private String typename;
  private int offset = -1; // XXX make sure this is correct
  private boolean unshared;
  private boolean persistent = false;
  private boolean toset = true;
  Field field;

  ObjectStreamField (Field field)
  {
    this (field.getName(), field.getType());
    this.field = field;
  }

  /**
   * This constructor creates an ObjectStreamField instance
   * which represents a field named <code>name</code> and is
   * of the type <code>type</code>.
   *
   * @param name Name of the field to export.
   * @param type Type of the field in the concerned class.
   */
  public ObjectStreamField (String name, Class<?> type)
  {
    this (name, type, false);
  }

  /**
   * This constructor creates an ObjectStreamField instance
   * which represents a field named <code>name</code> and is
   * of the type <code>type</code>.
   *
   * @param name Name of the field to export.
   * @param type Type of the field in the concerned class.
   * @param unshared true if field will be unshared, false otherwise.
   */
  public ObjectStreamField (String name, Class<?> type, boolean unshared)
  {
    if (name == null)
      throw new NullPointerException();

    this.name = name;
    this.type = type;
    this.typename = TypeSignature.getEncodingOfClass(type);
    this.unshared = unshared;
  }

  /**
   * There are many cases you can not get java.lang.Class from typename
   * if your context class loader cannot load it, then use typename to
   * construct the field.
   *
   * @param name Name of the field to export.
   * @param typename The coded name of the type for this field.
   */
  ObjectStreamField (String name, String typename)
  {
    this.name = name;
    this.typename = typename;
  }

  void resolveType(ClassLoader loader)
  {
    try
      {
        type = TypeSignature.getClassForEncoding(typename, true, loader);
      }
    catch(ClassNotFoundException e)
      {
      }
  }

  /**
   * This method returns the name of the field represented by the
   * ObjectStreamField instance.
   *
   * @return A string containing the name of the field.
   */
  public String getName ()
  {
    return name;
  }

  /**
   * This method returns the class representing the type of the
   * field which is represented by this instance of ObjectStreamField.
   *
   * @return A class representing the type of the field.
   */
  public Class<?> getType ()
  {
    return type;
  }

  /**
   * This method returns the char encoded type of the field which
   * is represented by this instance of ObjectStreamField.
   *
   * @return A char representing the type of the field.
   */
  public char getTypeCode ()
  {
    return typename.charAt (0);
  }

  /**
   * This method returns a more explicit type name than
   * {@link #getTypeCode()} in the case the type is a real
   * class (and not a primitive).
   *
   * @return The name of the type (class name) if it is not a
   * primitive, in the other case null is returned.
   */
  public String getTypeString ()
  {
    // use intern()
    if (isPrimitive())
      return null;
    return typename.intern();
  }

  /**
   * This method returns the current offset of the field in
   * the serialization stream relatively to the other fields.
   * The offset is expressed in bytes.
   *
   * @return The offset of the field in bytes.
   * @see #setOffset(int)
   */
  public int getOffset ()
  {
    return offset;
  }

  /**
   * This method sets the current offset of the field.
   *
   * @param off The offset of the field in bytes.
   * @see #getOffset()
   */
  protected void setOffset (int off)
  {
    offset = off;
  }

  /**
   * This method returns whether the field represented by this object is
   * unshared or not.
   *
   * @return Tells if this field is unshared or not.
   */
  public boolean isUnshared ()
  {
    return unshared;
  }

  /**
   * This method returns true if the type of the field
   * represented by this instance is a primitive.
   *
   * @return true if the type is a primitive, false
   * in the other case.
   */
  public boolean isPrimitive ()
  {
    return typename.length() == 1;
  }

  /**
   * Compares this object to the given object.
   *
   * @param obj the object to compare to.
   *
   * @return -1, 0 or 1.
   */
  public int compareTo (Object obj)
  {
    ObjectStreamField f = (ObjectStreamField) obj;
    boolean this_is_primitive = isPrimitive ();
    boolean f_is_primitive = f.isPrimitive ();

    if (this_is_primitive && !f_is_primitive)
      return -1;

    if (!this_is_primitive && f_is_primitive)
      return 1;

    return getName ().compareTo (f.getName ());
  }

  /**
   * This method is specific to classpath's implementation and so has the default
   * access. It changes the state of this field to "persistent". It means that
   * the field should not be changed when the stream is read (if it is not
   * explicitly specified using serialPersistentFields).
   *
   * @param persistent True if the field is persistent, false in the
   * other cases.
   * @see #isPersistent()
   */
  void setPersistent(boolean persistent)
  {
    this.persistent = persistent;
  }

  /**
   * This method returns true if the field is marked as persistent.
   *
   * @return True if persistent, false in the other cases.
   * @see #setPersistent(boolean)
   */
  boolean isPersistent()
  {
    return persistent;
  }

  /**
   * This method is specific to classpath's implementation and so
   * has the default access. It changes the state of this field as
   * to be set by ObjectInputStream.
   *
   * @param toset True if this field should be set, false in the other
   * cases.
   * @see #isToSet()
   */
  void setToSet(boolean toset)
  {
    this.toset = toset;
  }

  /**
   * This method returns true if the field is marked as to be
   * set.
   *
   * @return True if it is to be set, false in the other cases.
   * @see #setToSet(boolean)
   */
  boolean isToSet()
  {
    return toset;
  }

  /**
   * This method searches for its field reference in the specified class
   * object. It requests privileges. If an error occurs the internal field
   * reference is not modified.
   *
   * @throws NoSuchFieldException if the field name does not exist in this class.
   * @throws SecurityException if there was an error requesting the privileges.
   */
  void lookupField(Class clazz) throws NoSuchFieldException, SecurityException
  {
    final Field f = clazz.getDeclaredField(name);

    AccessController.doPrivileged(new PrivilegedAction()
      {
        public Object run()
        {
          f.setAccessible(true);
          return null;
        }
      });

    this.field = f;
  }

  /**
   * This method check whether the field described by this
   * instance of ObjectStreamField is compatible with the
   * actual implementation of this field.
   *
   * @throws NullPointerException if this field does not exist
   * in the real class.
   * @throws InvalidClassException if the types are incompatible.
   */
  void checkFieldType() throws InvalidClassException
  {
    Class<?> ftype = field.getType();

    if (!ftype.isAssignableFrom(type))
      throw new InvalidClassException
        ("invalid field type for " + name +
         " in class " + field.getDeclaringClass());
  }

  /**
   * Returns a string representing this object.
   *
   * @return the string.
   */
  public String toString ()
  {
    return "ObjectStreamField< " + type + " " + name + " >";
  }

  final void setBooleanField(Object obj, boolean val)
  {
    VMObjectStreamClass.setBooleanNative(field, obj, val);
  }

  final void setByteField(Object obj, byte val)
  {
    VMObjectStreamClass.setByteNative(field, obj, val);
  }

  final void setCharField(Object obj, char val)
  {
    VMObjectStreamClass.setCharNative(field, obj, val);
  }

  final void setShortField(Object obj, short val)
  {
    VMObjectStreamClass.setShortNative(field, obj, val);
  }

  final void setIntField(Object obj, int val)
  {
    VMObjectStreamClass.setIntNative(field, obj, val);
  }

  final void setLongField(Object obj, long val)
  {
    VMObjectStreamClass.setLongNative(field, obj, val);
  }

  final void setFloatField(Object obj, float val)
  {
    VMObjectStreamClass.setFloatNative(field, obj, val);
  }

  final void setDoubleField(Object obj, double val)
  {
    VMObjectStreamClass.setDoubleNative(field, obj, val);
  }

  final void setObjectField(Object obj, Object val)
  {
    VMObjectStreamClass.setObjectNative(field, obj, val);
  }
}
