/*
 * Copyright (c) 1996, 2004, 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.
 */
/*
 * Licensed Materials - Property of IBM
 * RMI-IIOP v1.0
 * Copyright IBM Corp. 1998 1999  All Rights Reserved
 *
 */

package com.sun.corba.se.impl.corba;


import org.omg.CORBA.Any;
import org.omg.CORBA.ARG_IN;
import org.omg.CORBA.ARG_OUT;
import org.omg.CORBA.ARG_INOUT;
import org.omg.CORBA.Context;
import org.omg.CORBA.ContextList;
import org.omg.CORBA.Environment;
import org.omg.CORBA.ExceptionList;
import org.omg.CORBA.NVList;
import org.omg.CORBA.NamedValue;
import org.omg.CORBA.Request;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.TypeCodePackage.BadKind;
import org.omg.CORBA.UnknownUserException;
import org.omg.CORBA.Bounds;
import org.omg.CORBA.UNKNOWN;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.WrongTransaction;

import org.omg.CORBA.portable.ApplicationException ;
import org.omg.CORBA.portable.RemarshalException ;
import org.omg.CORBA.portable.InputStream ;
import org.omg.CORBA.portable.OutputStream ;

import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
import com.sun.corba.se.impl.corba.AsynchInvoke;

public class RequestImpl
    extends Request
{
    ///////////////////////////////////////////////////////////////////////////
    // data members

    protected org.omg.CORBA.Object _target;
    protected String             _opName;
    protected NVList             _arguments;
    protected ExceptionList      _exceptions;
    private NamedValue           _result;
    protected Environment        _env;
    private Context              _ctx;
    private ContextList          _ctxList;
    protected ORB                _orb;
    private ORBUtilSystemException _wrapper;

    // invocation-specific stuff
    protected boolean            _isOneWay      = false;
    private int[]                _paramCodes;
    private long[]               _paramLongs;
    private java.lang.Object[]   _paramObjects;

    // support for deferred invocations.
    // protected instead of private since it needs to be set by the
    // thread object doing the asynchronous invocation.
    protected boolean            gotResponse    = false;

    ///////////////////////////////////////////////////////////////////////////
    // constructor

    // REVISIT - used to be protected.  Now public so it can be
    // accessed from xgiop.
    public RequestImpl (ORB orb,
                        org.omg.CORBA.Object targetObject,
                        Context ctx,
                        String operationName,
                        NVList argumentList,
                        NamedValue resultContainer,
                        ExceptionList exceptionList,
                        ContextList ctxList)
    {

        // initialize the orb
        _orb    = orb;
        _wrapper = ORBUtilSystemException.get( orb,
            CORBALogDomains.OA_INVOCATION ) ;

        // initialize target, context and operation name
        _target     = targetObject;
        _ctx    = ctx;
        _opName = operationName;

        // initialize argument list if not passed in
        if (argumentList == null)
            _arguments = new NVListImpl(_orb);
        else
            _arguments = argumentList;

        // set result container.
        _result = resultContainer;

        // initialize exception list if not passed in
        if (exceptionList == null)
            _exceptions = new ExceptionListImpl();
        else
            _exceptions = exceptionList;

        // initialize context list if not passed in
        if (ctxList == null)
            _ctxList = new ContextListImpl(_orb);
        else
            _ctxList = ctxList;

        // initialize environment
        _env    = new EnvironmentImpl();

    }

    public org.omg.CORBA.Object target()
    {
        return _target;
    }

    public String operation()
    {
        return _opName;
    }

    public NVList arguments()
    {
        return _arguments;
    }

    public NamedValue result()
    {
        return _result;
    }

    public Environment env()
    {
        return _env;
    }

    public ExceptionList exceptions()
    {
        return _exceptions;
    }

    public ContextList contexts()
    {
        return _ctxList;
    }

    public synchronized Context ctx()
    {
        if (_ctx == null)
            _ctx = new ContextImpl(_orb);
        return _ctx;
    }

    public synchronized void ctx(Context newCtx)
    {
        _ctx = newCtx;
    }

    public synchronized Any add_in_arg()
    {
        return _arguments.add(org.omg.CORBA.ARG_IN.value).value();
    }

    public synchronized Any add_named_in_arg(String name)
    {
        return _arguments.add_item(name, org.omg.CORBA.ARG_IN.value).value();
    }

    public synchronized Any add_inout_arg()
    {
        return _arguments.add(org.omg.CORBA.ARG_INOUT.value).value();
    }

    public synchronized Any add_named_inout_arg(String name)
    {
        return _arguments.add_item(name, org.omg.CORBA.ARG_INOUT.value).value();
    }

    public synchronized Any add_out_arg()
    {
        return _arguments.add(org.omg.CORBA.ARG_OUT.value).value();
    }

    public synchronized Any add_named_out_arg(String name)
    {
        return _arguments.add_item(name, org.omg.CORBA.ARG_OUT.value).value();
    }

    public synchronized void set_return_type(TypeCode tc)
    {
        if (_result == null)
            _result = new NamedValueImpl(_orb);
        _result.value().type(tc);
    }

    public synchronized Any return_value()
    {
        if (_result == null)
            _result = new NamedValueImpl(_orb);
        return _result.value();
    }

    public synchronized void add_exception(TypeCode exceptionType)
    {
        _exceptions.add(exceptionType);
    }

    public synchronized void invoke()
    {
        doInvocation();
    }

    public synchronized void send_oneway()
    {
        _isOneWay = true;
        doInvocation();
    }

    public synchronized void send_deferred()
    {
        AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false);
        new Thread(invokeObject).start();
    }

    public synchronized boolean poll_response()
    {
        // this method has to be synchronized even though it seems
        // "readonly" since the thread object doing the asynchronous
        // invocation can potentially update this variable in parallel.
        // updates are currently simply synchronized againt the request
        // object.
        return gotResponse;
    }

    public synchronized void get_response()
        throws org.omg.CORBA.WrongTransaction
    {
        while (gotResponse == false) {
            // release the lock. wait to be notified by the thread that is
            // doing the asynchronous invocation.
            try {
                wait();
            }
            catch (InterruptedException e) {}
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // private helper methods

    /*
     * The doInvocation operation is where the real mechanics of
     * performing the request invocation is done.
     */
    protected void doInvocation()
    {
        org.omg.CORBA.portable.Delegate delegate = StubAdapter.getDelegate(
            _target ) ;

        // Initiate Client Portable Interceptors.  Inform the PIHandler that
        // this is a DII request so that it knows to ignore the second
        // inevitable call to initiateClientPIRequest in createRequest.
        // Also, save the RequestImpl object for later use.
        _orb.getPIHandler().initiateClientPIRequest( true );
        _orb.getPIHandler().setClientPIInfo( this );

        InputStream $in = null;
        try {
            OutputStream $out = delegate.request(null, _opName, !_isOneWay);
            // Marshal args
            try {
                for (int i=0; i<_arguments.count() ; i++) {
                    NamedValue nv = _arguments.item(i);
                    switch (nv.flags()) {
                    case ARG_IN.value:
                        nv.value().write_value($out);
                        break;
                    case ARG_OUT.value:
                        break;
                    case ARG_INOUT.value:
                        nv.value().write_value($out);
                        break;
                    }
                }
            } catch ( org.omg.CORBA.Bounds ex ) {
                throw _wrapper.boundsErrorInDiiRequest( ex ) ;
            }

            $in = delegate.invoke(null, $out);
        } catch (ApplicationException e) {
            // REVISIT - minor code.
            // This is already handled in subcontract.
            // REVISIT - uncomment.
            //throw new INTERNAL();
        } catch (RemarshalException e) {
            doInvocation();
        } catch( SystemException ex ) {
            _env.exception(ex);
            // NOTE: The exception should not be thrown.
            // However, JDK 1.4 and earlier threw the exception,
            // so we keep the behavior to be compatible.
            throw ex;
        } finally {
            delegate.releaseReply(null, $in);
        }
    }

    // REVISIT -  make protected after development - so xgiop can get it.
    public void unmarshalReply(InputStream is)
    {
        // First unmarshal the return value if it is not void
        if ( _result != null ) {
            Any returnAny = _result.value();
            TypeCode returnType = returnAny.type();
            if ( returnType.kind().value() != TCKind._tk_void )
                returnAny.read_value(is, returnType);
        }

        // Now unmarshal the out/inout args
        try {
            for ( int i=0; i<_arguments.count() ; i++) {
                NamedValue nv = _arguments.item(i);
                switch( nv.flags() ) {
                case ARG_IN.value:
                    break;
                case ARG_OUT.value:
                case ARG_INOUT.value:
                    Any any = nv.value();
                    any.read_value(is, any.type());
                    break;
                }
            }
        }
        catch ( org.omg.CORBA.Bounds ex ) {
            // Cannot happen since we only iterate till _arguments.count()
        }
    }
}
