/* RmiUtilities.java --
   Copyright (C) 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 gnu.javax.rmi.CORBA;

import gnu.CORBA.OrbFunctional;
import gnu.CORBA.Minor;
import gnu.CORBA.Unexpected;
import gnu.CORBA.CDR.Vio;
import gnu.CORBA.CDR.gnuRuntime;
import gnu.CORBA.CDR.gnuValueStream;
import gnu.CORBA.CDR.HeadlessInput;

import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.StringValueHelper;
import org.omg.CORBA.WStringValueHelper;
import org.omg.CORBA.portable.Delegate;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CORBA.portable.OutputStream;
import org.omg.CORBA.portable.ValueBase;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.POAManagerPackage.State;
import org.omg.SendingContext.RunTime;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.rmi.Remote;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.WeakHashMap;

import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Stub;
import javax.rmi.CORBA.Tie;
import javax.rmi.CORBA.Util;

/**
 * Defines methods that must be accessible in several derived classes.
 * 
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class RmiUtilities
{
  /**
   * The currently used RMI-IIOP version format.
   */
  public static byte VERSION = 1;

  /**
   * The non - writable class fields.
   */
  static final int NON_WRITABLE = Modifier.STATIC | Modifier.TRANSIENT;

  /**
   * The standard String repository Id.
   */
  public static final String RMI_STRING_ID = StringValueHelper.id();

  /**
   * The standard Class repository Id.
   */
  public static final String RMI_CLASS_ID = "RMI:javax.rmi.CORBA.ClassDesc:2BABDA04587ADCCC:CFBF02CF5294176B";

  /**
   * The standard string array repository Id.
   */
  public static final String RMI_STRING_ARRAY_ID = "RMI:[Ljava.lang.String;:071DA8BE7F971128:A0F0A4387A3BB342";

  /**
   * An instance of the wide string value helper for writing strings.
   */
  static WStringValueHelper wStringValueHelper = new WStringValueHelper();

  /**
   * Set of serializable classes that have .writeObject and .readObject defined.
   * Contains weak references to ensure that the classes will be unloadable.
   */
  WeakHashMap io_format = new WeakHashMap();

  /**
   * The standard IO format with no .writeObject and .readObject defined.
   */
  static final Object STANDARD = new Object();

  /**
   * The custom IO format with .writeObject and .readObject defined,
   * defaultWriteObject called.
   */
  static final Object CUSTOM_DWO = new Object();

  /**
   * The custom IO format with .writeObject and .readObject defined,
   * defaultWriteObject has not been called.
   */
  static final Object CUSTOM_NO_DWO = new Object();

  /**
   * The arguments for readObject.
   */
  static final Class[] READ_OBJECT_ARGS = new Class[] { ObjectInputStream.class };

  /**
   * The arguments for writeObject.
   */
  static final Class[] WRITE_OBJECT_ARGS = new Class[] { ObjectOutputStream.class };

  /**
   * The undocumented field that is heading the Sun's object data, written with
   * writeObject.
   */
  static final int S_X = 16908034;

  /**
   * Write all fields of the passed value.
   */
  void writeFields(OutputStream an_output, Serializable object)
  {
    org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;
    try
      {
        Class o_class = object.getClass();
        Field[] fields = getWritableFields(o_class);
        Field f;

        Class fc;

        for (int i = 0; i < fields.length; i++)
          {
            f = fields[i];
            fc = f.getType();
            Object v = f.get(object);

            if (fc == String.class)
              {
                output.write_value((Serializable) v, wStringValueHelper);
              }
            else if (fc == int.class)
              output.write_long(((Integer) v).intValue());
            else if (fc == long.class)
              output.write_longlong(((Number) v).longValue());
            else if (fc == double.class)
              output.write_double(((Number) v).doubleValue());
            else if (fc == float.class)
              output.write_float(((Number) v).floatValue());
            else if (fc == boolean.class)
              output.write_boolean(((Boolean) v).booleanValue());
            else if (fc == short.class)
              output.write_short(((Number) v).shortValue());
            else if (fc == byte.class)
              output.write_octet(((Number) v).byteValue());
            else if (fc == char.class)
              output.write_wchar(((Character) v).charValue());
            else
              {
                if (!fc.isInterface() && Remote.class.isAssignableFrom(fc))
                  fc = getExportedInterface(fc);
                writeMember(output, v, fc);
              }
          }
      }
    catch (Exception ex)
      {
        MARSHAL m = new MARSHAL("Cannot write " + object);
        m.minor = Minor.ValueFields;
        m.initCause(ex);
        throw m;
      }
  }

  /**
   * Write a memeber (field) of the data structure.
   */
  void writeMember(org.omg.CORBA_2_3.portable.OutputStream output,
    Object object, Class xClass)
  {
    if (output instanceof gnuValueStream)
      {
        gnuRuntime g = ((gnuValueStream) output).getRunTime();
        // Reset the target as we are already beyond the critical point
        // where is must have the value being written.
        if (g != null)
          g.target = null;
      }
    if (Serializable.class.isAssignableFrom(xClass)
      || Remote.class.isAssignableFrom(xClass))
      {
        // Object handles null reference on its own.
        if (org.omg.CORBA.Object.class.isAssignableFrom(xClass)
          || Remote.class.isAssignableFrom(xClass))
          {
            if (object == null)
              output.write_Object(null);
            else if (isTieRequired(object))
              exportTie(output, object, xClass);
            else
              writeValue(output, (Serializable) object);
          }
        else
          output.write_value((Serializable) object, xClass);
      }
    else
      {
        MARSHAL m = new MARSHAL(xClass + " is not Serializable");
        m.minor = Minor.NonSerializable;
        throw m;
      }
  }

  /**
   * Check if the object must be wrapped into Tie, connected to the ORB and then
   * the corresponding Stub be written.
   */
  public boolean isTieRequired(Object object)
  {
    return object instanceof Remote && !(object instanceof Stub);
  }

  /**
   * Get the interface under that the class of this object must be exposed. The
   * interface must be derived from Remote.
   */
  Class getExportedInterface(Object object)
    throws MARSHAL
  {
    Class fc = null;
    Class[] interfaces = object.getClass().getInterfaces();
    for (int i = 0; i < interfaces.length; i++)
      {
        if (!Remote.class.equals(interfaces[i]))
          if (Remote.class.isAssignableFrom(interfaces[i]))
            {
              if (fc == null)
                fc = interfaces[i];
              else
                {
                  MARSHAL m = new MARSHAL("Both " + fc + " and " + interfaces[i]
                  + " extends Remote");
                  m.minor = Minor.TargetConversion;
                  throw m;
                }
            }
      }
    if (fc == null)
      {
        MARSHAL m = new MARSHAL(object.getClass()
        + " does not implement any interface, derived from Remote");
        m.minor = Minor.TargetConversion;
        throw m;
      }
    return fc;
  }

  /**
   * Get the persistent hash code for the given class, as defined by OMG
   * standard. The inheritance, field names and types (but not the visibility)
   * are taken into consideration as well as the presence of the writeObject
   * method are taken into consideration. The class name and methods, if any,
   * are not taken into consideration.
   */
  public static long getHashCode(Class c)
  {
    Class of = c.isArray() ? c.getComponentType() : null;
    if (c.isArray()
      && ((!Serializable.class.isAssignableFrom(of) || of.isPrimitive() || Remote.class.isAssignableFrom(of))))
      return 0;
    if (!Serializable.class.isAssignableFrom(c))
      return 0;
    try
      {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        DataOutputStream out = new DataOutputStream(bout);

        Class superClass = c.getSuperclass();
        if (superClass != null)
          out.writeLong(getHashCode(superClass));

        int writeObjectPresentCode;
        try
          {
            c.getDeclaredMethod("writeObject",
              new Class[] { ObjectOutputStream.class });
            writeObjectPresentCode = 2; // Exists.
          }
        catch (NoSuchMethodException e)
          {
            writeObjectPresentCode = 1; // Missing.
          }
        out.writeInt(writeObjectPresentCode);

        Field[] fields = c.getDeclaredFields();

        Arrays.sort(fields, new Comparator()
        {
          public int compare(Object a, Object b)
          {
            Field fa = (Field) a;
            Field fb = (Field) b;
            return fa.getName().compareTo(fb.getName());
          }
        });

        Field f;
        for (int i = 0; i < fields.length; i++)
          {
            f = fields[i];
            if ((f.getModifiers() & NON_WRITABLE) == 0)
              {
                out.writeUTF(f.getName());
                out.writeUTF(getDescriptor(f.getType()));
              }
          }

        out.flush();
        out.close();
        MessageDigest shaDigest;
        try
          {
            shaDigest = MessageDigest.getInstance("SHA");
          }
        catch (Exception ex)
          {
            throw new InternalError("SHA digesting algorithm is not available");
          }

        // Return the digest value to the calling
        // method as an array of bytes.
        byte[] sha = shaDigest.digest(bout.toByteArray());

        long hash = 0;
        for (int i = 0; i < Math.min(8, sha.length); i++)
          {
            hash += (long) (sha[i] & 255) << (i * 8);
          }
        return hash;
      }
    catch (IOException ioex)
      {
        throw new Unexpected(ioex);
      }
  }

  /**
   * Converts to hexadecimal string, supplementing leading zeros.
   */
  public static String toHex(long l)
  {
    StringBuffer b = new StringBuffer();
    b.append(Long.toHexString(l).toUpperCase());
    while (b.length() < 16)
      b.insert(0, '0');
    return b.toString();
  }

  /**
   * Returns a <code>String</code> representing the type-encoding of a class.
   */
  static String getDescriptor(Class type)
  {
    if (type.equals(boolean.class))
      return "Z";
    if (type.equals(byte.class))
      return "B";
    if (type.equals(short.class))
      return "S";
    if (type.equals(char.class))
      return "C";
    if (type.equals(int.class))
      return "I";
    if (type.equals(long.class))
      return "J";
    if (type.equals(float.class))
      return "F";
    if (type.equals(double.class))
      return "D";
    if (type.equals(void.class))
      return "V";
    else if (type.isArray())
      {
        StringBuffer l = new StringBuffer("[");
        Class component = type.getComponentType();

        while (component.isArray())
          {
            l.append('[');
            component = component.getComponentType();
          }

        l.append('L');
        l.append(component.getName().replace('.', '/'));
        l.append(';');
        return l.toString();
      }
    else
      return "L" + type.getName().replace('.', '/') + ';';
  }

  public static Field[] getWritableFields(Class c)
  {
    TreeSet set = new TreeSet(new Comparator()
    {
      public int compare(Object a, Object b)
      {
        return ((Field) a).getName().compareTo(((Field) b).getName());
      }
    });

    while (!c.equals(Object.class))
      {
        Field[] f = c.getDeclaredFields();
        for (int i = 0; i < f.length; i++)
          {
            if ((f[i].getModifiers() & NON_WRITABLE) == 0)
              {
                f[i].setAccessible(true);
                set.add(f[i]);
              }
          }
        c = c.getSuperclass();
      }

    Field[] r = new Field[set.size()];
    int p = 0;
    Iterator it = set.iterator();
    while (it.hasNext())
      {
        r[p++] = (Field) it.next();
      }
    return r;
  }

  /**
   * The method is called for Remotes that are not Stubs. It is assumed, that
   * the Remote is an implementation. The method searches for the suitable tie
   * and, if found, exports it by creating and connecting the stub. Such export
   * is supported since jdk 1.5.
   */
  void exportTie(org.omg.CORBA_2_3.portable.OutputStream output,
    Object implementation, Class interfaceClass)
  {
    try
      {
        // Remote, but non - stub class (implementation)
        // must be replaced by stub.
        Tie t = Util.getTie((Remote) implementation);
        if (t instanceof Servant)
          {
            POA rootPoa = POAHelper.narrow(output.orb().resolve_initial_references(
              "RootPOA"));
            org.omg.CORBA.Object co = rootPoa.servant_to_reference((Servant) t);
            Stub stub = (Stub) PortableRemoteObject.narrow(co, interfaceClass);
            writeRemoteObject(output, stub);

            if (rootPoa.the_POAManager().get_state().value() == State._HOLDING)
              rootPoa.the_POAManager().activate();
          }
        else if (t instanceof org.omg.CORBA.Object)
          {
            org.omg.CORBA.Object co = (org.omg.CORBA.Object) t;
            output.orb().connect(co);

            Stub stub = (Stub) PortableRemoteObject.narrow(co, interfaceClass);
            writeRemoteObject(output, stub);
          }
      }
    catch (Exception ex)
      {
        MARSHAL m = new MARSHAL("Unable to export " + implementation);
        m.minor = Minor.TargetConversion;
        m.initCause(ex);
        throw m;
      }
  }

  /**
   * Start the ORB, if it is not already runnning.
   */
  void ensureOrbRunning(org.omg.CORBA_2_3.portable.OutputStream output)
  {
    // Ensure ORB is running.
    if (output.orb() instanceof OrbFunctional)
      {
        ((OrbFunctional) output.orb()).ensureRunning();
      }
  }

  /**
   * Write data to the CORBA output stream. Writes the object contents only; the
   * header must be already written. For object, containing objects, may be
   * called recursively.
   * 
   * @param an_output a stream to write to, must be
   * org.omg.CORBA_2_3.portable.OutputStream
   * @param object an object to write.
   */
  public void writeRemoteObject(OutputStream an_output, Object object)
  {
    org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;

    if (isTieRequired(object))
      {
        // Find the interface that is implemented by the object and extends
        // Remote.
        Class fc = getExportedInterface(object);
        exportTie(output, object, fc);
      }
    else if (object instanceof org.omg.CORBA.Object)
      {
        ensureOrbRunning(output);
        an_output.write_Object((org.omg.CORBA.Object) object);
      }
    else if (object != null && object instanceof Serializable)
      writeFields(an_output, (Serializable) object);
  }

  /**
   * Write data to the CORBA output stream. Writes the object contents only; the
   * header must be already written. For object, containing objects, may be
   * called recursively.
   * 
   * @param an_output a stream to write to, must be
   * org.omg.CORBA_2_3.portable.OutputStream
   * @param object an object to write.
   */
  public void writeValue(OutputStream an_output, Serializable object)
  {
    org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;

    if (isTieRequired(object))
      {
        // Find the interface that is implemented by the object and extends
        // Remote.
        Class fc = getExportedInterface(object);
        exportTie(output, object, fc);
      }
    else if (object instanceof org.omg.CORBA.Object)
      {
        ensureOrbRunning(output);
        an_output.write_Object((org.omg.CORBA.Object) object);
      }
    else if (object instanceof Externalizable)
      {
        try
          {
            ObjectOutputStream stream = new CorbaOutput(output, object,
              this);
            stream.write(VERSION);
            ((Externalizable) object).writeExternal(stream);
          }
        catch (Exception ex)
          {
            MARSHAL m = new MARSHAL("writeExternal failed");
            m.minor = Minor.Value;
            m.initCause(ex);
            throw m;
          }
      }
    else if (object instanceof Serializable)
      {
        Object mode = null;
        synchronized (io_format)
          {
            mode = io_format.get(object.getClass());
            if (mode == STANDARD)
              {
                writeFields(an_output, (Serializable) object);
                return;
              }
          }
        try
          {
            Method m = object.getClass().getDeclaredMethod("writeObject",
              WRITE_OBJECT_ARGS);
            m.setAccessible(true); // May be private.

            try
              {
                ObjectOutputStream stream = new CorbaOutput(output,
                  object, this);

                // Write version.
                stream.write(VERSION);

                if (mode == CUSTOM_DWO)
                  // Write true, supposing that the defaultWriteObject
                  // has been called.
                  stream.write(1);
                else if (mode == CUSTOM_NO_DWO)
                  // Write false (has not been called)
                  stream.write(0);
                else
                  {
                    // Measure.
                    DefaultWriteObjectTester tester = new DefaultWriteObjectTester(object);
                    m.invoke(object, new Object[] { tester });

                    synchronized (io_format)
                      {
                        io_format.put(object.getClass(),
                          tester.dwo_called ? CUSTOM_DWO : CUSTOM_NO_DWO);
                        stream.write(tester.dwo_called ? 1 : 0);
                      }
                  }

                m.invoke(object, new Object[] { stream });
                stream.flush();
              }
            catch (Exception ex)
              {
                MARSHAL mx = new MARSHAL(object.getClass().getName()
                  + ".writeObject failed");
                mx.initCause(ex);
                throw mx;
              }
          }
        catch (NoSuchMethodException e)
          {
            // Write in a standard way.
            writeFields(an_output, (Serializable) object);
            synchronized (io_format)
              {
                io_format.put(object.getClass(), STANDARD);
              }
          }
      }
  }

  /**
   * Read data from the CDR input stream. Reads the object contents only; the
   * header must be already read (the repository id or ids ara passed). For
   * object, containing objects, may be called recursively.
   * 
   * @param an_input the stream to read from, must be
   * org.omg.CORBA_2_3.portable.InputStream
   * @param object the instance of the object being read.
   * @param id the repository Id from the stream in the case when single id was
   * specified.
   * @param ids the repository Ids from the stream in the case when multiple ids
   * were specified.
   * @param codebase the codebase, if it was included in the header of the value
   * type. Null if not codebase was included.
   * 
   * @return the object, extracted from the stream.
   */
  /**
   * Read value from the input stream in the case when the value is not
   * Streamable or CustomMarshalled.
   */
  public Serializable readValue(InputStream in, int offset, Class clz,
    String repositoryID, RunTime sender)
  {
    if (in instanceof HeadlessInput)
      ((HeadlessInput) in).subsequentCalls = true;

    gnuRuntime g;
    Serializable object = null;

    try
      {
        g = (gnuRuntime) sender;
        object = g.target;
      }
    catch (ClassCastException e)
      {
        // Working with the other CORBA implementation.
        g = null;
      }

    org.omg.CORBA_2_3.portable.InputStream input = (org.omg.CORBA_2_3.portable.InputStream) in;

    if (Remote.class.isAssignableFrom(clz)
      || ValueBase.class.isAssignableFrom(clz))
      {
        // Interface is narrowed into Stub.
        if (clz.isInterface())
          try
            {
              clz = Util.loadClass(
                PortableRemoteObjectDelegateImpl.getStubClassName(clz.getName()),
                null, clz.getClassLoader());
            }
          catch (ClassNotFoundException e)
            {
              MARSHAL m = new MARSHAL("Cannot get stub from interface "
                + clz.getClass().getName());
              m.minor = Minor.TargetConversion;
              m.initCause(e);
              throw m;
            }

        // Remote needs special handling.
        if (ObjectImpl.class.isAssignableFrom(clz))
          {
            // First read CORBA object reference.
            Object ro = input.read_Object();

            ObjectImpl obj = (ObjectImpl) ro;
            if (obj == null)
              return null;

            Delegate delegate = obj._get_delegate();
            object = instantiate(offset, clz, g);
            ((ObjectImpl) object)._set_delegate(delegate);
          }
        // The object - specific data follows.
      }
    else if (org.omg.CORBA.Object.class.isAssignableFrom(clz))
      object = (Serializable) input.read_Object();

    if (object == null)
      object = instantiate(offset, clz, g);
    
    // The sentence below prevents attempt to read the internal fields of the
    // ObjectImpl (or RMI Stub) that might follow the object definition.
    // Sun's jre 1.5 does not write this information. The stubs, generated
    // by rmic, does not contain such fields.
    if (object instanceof ObjectImpl)
      return object;

    if (object instanceof Externalizable)
      {
        try
          {
            CorbaInput stream = new CorbaInput(input, object, this,
              offset, repositoryID, g);

            byte version = stream.readByte();
            if (version != 1)
              throw new MARSHAL("Unsuported RMI-IIOP version " + version);

            ((Externalizable) object).readExternal(stream);
          }
        catch (Exception ex)
          {
            MARSHAL m = new MARSHAL("readExternal failed");
            m.initCause(ex);
            throw m;
          }
      }
    else
      {
        Object mode = null;
        synchronized (io_format)
          {
            mode = io_format.get(object.getClass());
          }

        if (mode == STANDARD)
          {
            readFields(offset, repositoryID, object, input, g);
          }
        else
          {
            try
              {
                Method m = object.getClass().getDeclaredMethod("readObject",
                  READ_OBJECT_ARGS);
                try
                  {
                    m.setAccessible(true); // May be private.

                    CorbaInput stream = new CorbaInput(input,
                      object, this, offset, repositoryID, g);

                    byte version = stream.readByte();
                    if (version != 1)
                      throw new MARSHAL("Unsuported RMI-IIOP version "
                        + version);

                    // This would indicate is defaultWriteObject has been
                    // called,
                    // but the readObject method normally takes care about this.
                    boolean dwo = stream.readByte() != 0;

                    m.invoke(object, new Object[] { stream });
                    synchronized (io_format)
                      {
                        io_format.put(object.getClass(), dwo ? CUSTOM_DWO
                          : CUSTOM_NO_DWO);
                      }
                  }
                catch (Exception ex)
                  {
                    ex.printStackTrace();
                    MARSHAL mx = new MARSHAL(object.getClass().getName()
                      + ".readObject failed");
                    mx.initCause(ex);
                    throw mx;
                  }
              }
            catch (NoSuchMethodException e)
              {
                // Read in a standard way.
                synchronized (io_format)
                  {
                    io_format.put(object.getClass(), STANDARD);
                    readFields(offset, repositoryID, object, input, g);
                  }
              }
          }
      }
    return object;
  }

  /**
   * Create an instance.
   */
  Serializable instantiate(int offset, Class clz, gnuRuntime g)
    throws MARSHAL
  {
    Serializable object;
    try
      {
        object = (Serializable) Vio.instantiateAnyWay(clz);
        g.objectWritten(object, offset);
      }
    catch (Exception e)
      {
        MARSHAL m = new MARSHAL("Unable to instantiate " + clz);
        m.minor = Minor.Instantiation;
        m.initCause(e);
        throw m;
      }
    return object;
  }

  /**
   * Read fields of the object.
   */
  void readFields(int offset, String repositoryID, Serializable object,
    org.omg.CORBA_2_3.portable.InputStream input, gnuRuntime r)
    throws MARSHAL
  {
    Field f = null;
    Class o_class = object.getClass();

    try
      {
        // The returned field array must already be in canonical order.
        Field[] fields = getWritableFields(o_class);

        Class fc;

        for (int i = 0; i < fields.length; i++)
          {
            // Full value type header expected ahead.
            if (input instanceof HeadlessInput)
              ((HeadlessInput) input).subsequentCalls = true;

            f = fields[i];
            fc = f.getType();

            Object v;

            if (fc == String.class)
              {
                v = input.read_value(wStringValueHelper);
              }
            else if (fc == int.class)
              v = new Integer(input.read_long());
            else if (fc == long.class)
              v = new Long(input.read_longlong());
            else if (fc == double.class)
              v = new Double(input.read_double());
            else if (fc == float.class)
              v = new Float(input.read_float());
            else if (fc == boolean.class)
              v = input.read_boolean() ? Boolean.TRUE : Boolean.FALSE;
            else if (fc == short.class)
              v = new Short(input.read_short());
            else if (fc == byte.class)
              v = new Byte(input.read_octet());
            else if (fc == char.class)
              v = new Character(input.read_char());
            else if (org.omg.CORBA.Object.class.isAssignableFrom(fc)
              || Remote.class.isAssignableFrom(fc))
              {
                v = readValue(input, offset, fc, null, r);
              }
            else
              {
                v = Vio.read(input, fc);
              }

            f.set(object, v);
          }
      }
    catch (Exception ex)
      {
        MARSHAL m = new MARSHAL("Cannot read " + o_class.getName() + " field "
          + f);
        m.initCause(ex);
        m.minor = Minor.ValueFields;
        throw m;
      }
  }

}
