/* * 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() } } }