/* UnicastRemoteCall.java
   Copyright (c) 1996, 1997, 1998, 1999, 2002, 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 gnu.java.rmi.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.StreamCorruptedException;
import java.rmi.MarshalException;
import java.rmi.RemoteException;
import java.rmi.UnmarshalException;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteCall;
import java.rmi.server.UID;
import java.util.Vector;

public class UnicastRemoteCall
	implements RemoteCall, ProtocolConstants
{

  private UnicastConnection conn;
  private Object result;
  private Object object;
  private int opnum;
  private long hash;
  // These are package-private due to inner class access.
  Vector vec;
  int ptr;
  private ObjID objid;

  private ObjectOutput oout;
  private ObjectInput oin;

  /**
   * Incoming call.
   */
  UnicastRemoteCall(UnicastConnection conn)
  {
    this.conn = conn;
  }

  /**
   * Outgoing call.
   */
  UnicastRemoteCall(UnicastConnection conn, ObjID objid, int opnum, long hash)
    throws RemoteException
  {
    this.conn = conn;
    this.opnum = opnum;
    this.hash = hash;
    this.objid = objid;
  }
  
  UnicastConnection getConnection()
  {
    return conn;
  }
  
  public ObjectOutput getOutputStream() throws IOException
  {
    if (vec == null)
      vec = new Vector();
    return (new DummyObjectOutputStream());
  }

  public void releaseOutputStream() throws IOException
  {
    if (vec != null)
      {
	oout = conn.getObjectOutputStream();
	
	for (int i = 0; i < vec.size(); i += 2)
	  {
	    boolean primitive = ((Boolean)vec.elementAt(i)).booleanValue();
	    Object data = vec.elementAt(i+1);

	    // No type, this is
	    if (!primitive)
	      oout.writeObject(data);
	    else
	      {
		if (data instanceof Boolean)
		  oout.writeBoolean(((Boolean)data).booleanValue());
		else if (data instanceof Character)
		  oout.writeChar(((Character)data).charValue());
		else if (data instanceof Byte)
		  oout.writeByte(((Byte)data).byteValue());
		else if (data instanceof Short)
		  oout.writeShort(((Short)data).shortValue());
		else if (data instanceof Integer)
		  oout.writeInt(((Integer)data).intValue());
		else if (data instanceof Long)
		  oout.writeLong(((Long)data).longValue());
	      }
	  }
	vec = null;
      }
    if(oout != null)
      oout.flush();
  }

  /**
  *
  * (re)starts ObjectInputStream
  *
  */ 
  public ObjectInput startInputStream() throws IOException
  {
	if (conn != null) {
		return (oin = conn.startObjectInputStream());
	} else {
		return getInputStream(); // dummy Input Stream
	}

  }

  public ObjectInput getInputStream() throws IOException
  {
    if (conn != null)
      {
	if(oin == null)
	  return (oin = conn.getObjectInputStream());
	else
	  return oin;
      }
    else
      {
	ptr = 0;
	return (new DummyObjectInputStream());
      }
  }

  public void releaseInputStream() throws IOException
  {
    // Does nothing.
  }

  public ObjectOutput getResultStream(boolean success)
    throws IOException, StreamCorruptedException
  {
    vec = new Vector();
    return new DummyObjectOutputStream();
  }
  
  public void executeCall() throws Exception
  {
    byte returncode;
    ObjectInput oin;
    
    // signal the call when constructing
    try
      {
	DataOutputStream dout = conn.getDataOutputStream();
	dout.write(MESSAGE_CALL);
	
	oout = conn.startObjectOutputStream(); // (re)start ObjectOutputStream
	objid.write(oout);
	oout.writeInt(opnum);
	oout.writeLong(hash);
      }
    catch(IOException ex)
      {
	throw new MarshalException("Try to write header but failed.", ex);
      }

    try
      {
	releaseOutputStream();
	DataInputStream din = conn.getDataInputStream();
        if (din.readByte() != MESSAGE_CALL_ACK)
	    throw new RemoteException("Call not acked");

        oin = startInputStream();
        returncode = oin.readByte();
        UID.read(oin);
      }
    catch(IOException ex)
      {
        throw new UnmarshalException("Try to read header but failed:", ex);
      }
    
    //check return code
    switch(returncode)
      {
      case RETURN_ACK: //it's ok
	return;
      case RETURN_NACK:
	Object returnobj;
	try
	  {
	    returnobj = oin.readObject();
	  }
	catch(Exception ex2)
	  {
	    throw new UnmarshalException
	      ("Try to read exception object but failed", ex2);
	  }
	
	if(!(returnobj instanceof Exception))
	  throw new UnmarshalException("Should be Exception type here: "
				       + returnobj);
	throw (Exception)returnobj;
	
      default:
	throw new UnmarshalException("Invalid return code");
      }
  }

  public void done() throws IOException
  {
    // conn.disconnect();
  }

  boolean isReturnValue()
  {
    return vec.size() > 0;
  }
  
  Object returnValue()
  {
    // This is not the first one (Boolean) but the second.
    return vec.elementAt(1);
  }

  Object[] getArguments()
  {
    return vec.toArray();
  }

  Object getObject()
  {
    return object;
  }

  int getOpnum()
  {
    return opnum;
  }

  long getHash()
  {
    return hash;
  }

  void setReturnValue(Object obj)
  {
    vec.removeAllElements();
    vec.addElement(obj);
  }

  /**
   * Dummy object output class.
   */
  private class DummyObjectOutputStream implements ObjectOutput
  {
    /**
     * Non-private constructor to reduce bytecode emitted.
     */
    DummyObjectOutputStream()
    {
    }

    public void writeBoolean(boolean v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(Boolean.valueOf(v));
    }

    public void writeByte(int v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Byte((byte) v));
    }

    public void writeChar(int v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Character((char) v));
    }

    public void writeDouble(double v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Double(v));
    }

    public void writeFloat(float v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Float(v));
    }

    public void writeInt(int v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Integer(v));
    }

    public void writeLong(long v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Long(v));
    }

    public void writeShort(int v) throws IOException
    {
      vec.addElement(Boolean.TRUE);
      vec.addElement(new Short((short) v));
    }

    public void writeObject(Object obj) throws IOException
    {
      vec.addElement(Boolean.FALSE);
      vec.addElement(obj);
    }

    public void write(byte b[]) throws IOException
    {
      throw new IOException("not required");
    }

    public void write(byte b[], int off, int len) throws IOException
    {
      throw new IOException("not required");
    }

    public void write(int b) throws IOException
    {
      throw new IOException("not required");
    }

    public void writeBytes(String s) throws IOException
    {
      throw new IOException("not required");
    }

    public void writeChars(String s) throws IOException
    {
      throw new IOException("not required");
    }

    public void writeUTF(String str) throws IOException
    {
      throw new IOException("not required");
    }

    public void flush() throws IOException
    {
    }

    public void close() throws IOException
    {
    }
  } // class DummyObjectOutputStream

  /**
   * Dummy object input class.
   */
  private class DummyObjectInputStream implements ObjectInput
  {
    /**
     * Non-private constructor to reduce bytecode emitted.
     */
    DummyObjectInputStream()
    {
    }

    public boolean readBoolean() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Boolean) obj).booleanValue();
    }

    public byte readByte() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Byte) obj).byteValue();
    }

    public char readChar() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Character) obj).charValue();
    }

    public double readDouble() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Double) obj).doubleValue();
    }

    public float readFloat() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Float) obj).floatValue();
    }

    public int readInt() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Integer) obj).intValue();
    }

    public long readLong() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Long) obj).longValue();
    }

    public short readShort() throws IOException
    {
      Object obj = vec.elementAt(ptr++);
      return ((Short) obj).shortValue();
    }

    public Object readObject() throws IOException
    {
      return vec.elementAt(ptr++);
    }

    public int read(byte b[]) throws IOException
    {
      throw new IOException("not required");
    }

    public int read(byte b[], int off, int len) throws IOException
    {
      throw new IOException("not required");
    }

    public int read() throws IOException
    {
      throw new IOException("not required");
    }

    public long skip(long n) throws IOException
    {
      throw new IOException("not required");
    }

    public int available() throws IOException
    {
      throw new IOException("not required");
    }

    public void readFully(byte b[]) throws IOException
    {
      throw new IOException("not required");
    }

    public void readFully(byte b[], int off, int len) throws IOException
    {
      throw new IOException("not required");
    }

    public String readLine() throws IOException
    {
      throw new IOException("not required");
    }

    public String readUTF() throws IOException
    {
      throw new IOException("not required");
    }

    public int readUnsignedByte() throws IOException
    {
      throw new IOException("not required");
    }

    public int readUnsignedShort() throws IOException
    {
      throw new IOException("not required");
    }

    public int skipBytes(int n) throws IOException
    {
      throw new IOException("not required");
    }

    public void close() throws IOException
    {
    }
  } // class DummyObjectInputStream

}
