/*
 * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.rmi.transport;

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.ObjID;
import java.rmi.server.RemoteCall;
import sun.rmi.runtime.Log;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.tcp.TCPEndpoint;

/**
 * Stream-based implementation of the RemoteCall interface.
 *
 * @author Ann Wollrath
 */
public class StreamRemoteCall implements RemoteCall {
    private ConnectionInputStream in = null;
    private ConnectionOutputStream out = null;
    private Connection conn;
    private boolean resultStarted = false;
    private Exception serverException = null;

    public StreamRemoteCall(Connection c) {
        conn = c;
    }

    public StreamRemoteCall(Connection c, ObjID id, int op, long hash)
        throws RemoteException
    {
        try {
            conn = c;
            Transport.transportLog.log(Log.VERBOSE,
                "write remote call header...");

            // write out remote call header info...
            // call header, part 1 (read by Transport)
            conn.getOutputStream().write(TransportConstants.Call);
            getOutputStream();           // creates a MarshalOutputStream
            id.write(out);               // object id (target of call)
            // call header, part 2 (read by Dispatcher)
            out.writeInt(op);            // method number (operation index)
            out.writeLong(hash);         // stub/skeleton hash
        } catch (IOException e) {
            throw new MarshalException("Error marshaling call header", e);
        }
    }

    /**
     * Return the connection associated with this call.
     */
    public Connection getConnection() {
        return conn;
    }

    /**
     * Return the output stream the stub/skeleton should put arguments/results
     * into.
     */
    public ObjectOutput getOutputStream() throws IOException {
        return getOutputStream(false);
    }

    private ObjectOutput getOutputStream(boolean resultStream)
        throws IOException
    {
        if (out == null) {
            Transport.transportLog.log(Log.VERBOSE, "getting output stream");

            out = new ConnectionOutputStream(conn, resultStream);
        }
        return out;
    }

    /**
     * Release the outputStream  Currently, will not complain if the
     * output stream is released more than once.
     */
    public void releaseOutputStream() throws IOException {
        try {
            if (out != null) {
                try {
                    out.flush();
                } finally {
                    out.done();         // always start DGC ack timer
                }
            }
            conn.releaseOutputStream();
        } finally {
            out = null;
        }
    }

    /**
     * Get the InputStream the stub/skeleton should get results/arguments
     * from.
     */
    public ObjectInput getInputStream() throws IOException {
        if (in == null) {
            Transport.transportLog.log(Log.VERBOSE, "getting input stream");

            in = new ConnectionInputStream(conn.getInputStream());
        }
        return in;
    }

    /**
     * Release the input stream, this would allow some transports to release
     * the channel early.
     */
    public void releaseInputStream() throws IOException {
        /* WARNING: Currently, the UnicastRef.java invoke methods rely
         * upon this method not throwing an IOException.
         */

        try {
            if (in != null) {
                // execute MarshalInputStream "done" callbacks
                try {
                    in.done();
                } catch (RuntimeException e) {
                }

                // add saved references to DGC table
                in.registerRefs();

                /* WARNING: The connection being passed to done may have
                 * already been freed.
                 */
                in.done(conn);
            }
            conn.releaseInputStream();
        } finally {
            in = null;
        }
    }

    /**
     * Returns an output stream (may put out header information
     * relating to the success of the call).
     * @param success If true, indicates normal return, else indicates
     * exceptional return.
     * @exception StreamCorruptedException If result stream previously
     * acquired
     * @exception IOException For any other problem with I/O.
     */
    public ObjectOutput getResultStream(boolean success) throws IOException {
        /* make sure result code only marshaled once. */
        if (resultStarted)
            throw new StreamCorruptedException("result already in progress");
        else
            resultStarted = true;

        // write out return header
        // return header, part 1 (read by Transport)
        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
        wr.writeByte(TransportConstants.Return);// transport op
        getOutputStream(true);  // creates a MarshalOutputStream
        // return header, part 2 (read by client-side RemoteCall)
        if (success)            //
            out.writeByte(TransportConstants.NormalReturn);
        else
            out.writeByte(TransportConstants.ExceptionalReturn);
        out.writeID();          // write id for gcAck
        return out;
    }

    /**
     * Do whatever it takes to execute the call.
     */
    public void executeCall() throws Exception {
        byte returnType;

        // read result header
        DGCAckHandler ackHandler = null;
        try {
            if (out != null) {
                ackHandler = out.getDGCAckHandler();
            }
            releaseOutputStream();
            DataInputStream rd = new DataInputStream(conn.getInputStream());
            byte op = rd.readByte();
            if (op != TransportConstants.Return) {
                if (Transport.transportLog.isLoggable(Log.BRIEF)) {
                    Transport.transportLog.log(Log.BRIEF,
                        "transport return code invalid: " + op);
                }
                throw new UnmarshalException("Transport return code invalid");
            }
            getInputStream();
            returnType = in.readByte();
            in.readID();        // id for DGC acknowledgement
        } catch (UnmarshalException e) {
            throw e;
        } catch (IOException e) {
            throw new UnmarshalException("Error unmarshaling return header",
                                         e);
        } finally {
            if (ackHandler != null) {
                ackHandler.release();
            }
        }

        // read return value
        switch (returnType) {
        case TransportConstants.NormalReturn:
            break;

        case TransportConstants.ExceptionalReturn:
            Object ex;
            try {
                ex = in.readObject();
            } catch (Exception e) {
                throw new UnmarshalException("Error unmarshaling return", e);
            }

            // An exception should have been received,
            // if so throw it, else flag error
            if (ex instanceof Exception) {
                exceptionReceivedFromServer((Exception) ex);
            } else {
                throw new UnmarshalException("Return type not Exception");
            }
        default:
            if (Transport.transportLog.isLoggable(Log.BRIEF)) {
                Transport.transportLog.log(Log.BRIEF,
                    "return code invalid: " + returnType);
            }
            throw new UnmarshalException("Return code invalid");
        }
    }

    /**
     * Routine that causes the stack traces of remote exceptions to be
     * filled in with the current stack trace on the client.  Detail
     * exceptions are filled in iteratively.
     */
    protected void exceptionReceivedFromServer(Exception ex) throws Exception {
        serverException = ex;

        StackTraceElement[] serverTrace = ex.getStackTrace();
        StackTraceElement[] clientTrace = (new Throwable()).getStackTrace();
        StackTraceElement[] combinedTrace =
            new StackTraceElement[serverTrace.length + clientTrace.length];
        System.arraycopy(serverTrace, 0, combinedTrace, 0,
                         serverTrace.length);
        System.arraycopy(clientTrace, 0, combinedTrace, serverTrace.length,
                         clientTrace.length);
        ex.setStackTrace(combinedTrace);

        /*
         * Log the details of a server exception thrown as a result of a
         * remote method invocation.
         */
        if (UnicastRef.clientCallLog.isLoggable(Log.BRIEF)) {
            /* log call exception returned from server before it is rethrown */
            TCPEndpoint ep = (TCPEndpoint) conn.getChannel().getEndpoint();
            UnicastRef.clientCallLog.log(Log.BRIEF, "outbound call " +
                "received exception: [" + ep.getHost() + ":" +
                ep.getPort() + "] exception: ", ex);
        }

        throw ex;
    }

    /*
     * method to retrieve possible server side exceptions (which will
     * be throw from exceptionReceivedFromServer(...) )
     */
    public Exception getServerException() {
        return serverException;
    }

    public void done() throws IOException {
        /* WARNING: Currently, the UnicastRef.java invoke methods rely
         * upon this method not throwing an IOException.
         */

        releaseInputStream();
    }
}
