/* UnicastRemoteCall.java
  Copyright (c) 1996, 1997, 1998, 1999, 2002, 2004  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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.RemoteException;
import java.rmi.MarshalException;
import java.rmi.UnmarshalException;
import java.rmi.server.RemoteCall;
import java.rmi.server.ObjID;
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

}
