1 /*
   2  * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * Licensed Materials - Property of IBM
  27  * RMI-IIOP v1.0
  28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
  29  *
  30  */
  31 
  32 package com.sun.corba.se.impl.corba;
  33 
  34 
  35 import org.omg.CORBA.Any;
  36 import org.omg.CORBA.ARG_IN;
  37 import org.omg.CORBA.ARG_OUT;
  38 import org.omg.CORBA.ARG_INOUT;
  39 import org.omg.CORBA.Context;
  40 import org.omg.CORBA.ContextList;
  41 import org.omg.CORBA.Environment;
  42 import org.omg.CORBA.ExceptionList;
  43 import org.omg.CORBA.NVList;
  44 import org.omg.CORBA.NamedValue;
  45 import org.omg.CORBA.Request;
  46 import org.omg.CORBA.SystemException;
  47 import org.omg.CORBA.TCKind;
  48 import org.omg.CORBA.TypeCode;
  49 import org.omg.CORBA.TypeCodePackage.BadKind;
  50 import org.omg.CORBA.UnknownUserException;
  51 import org.omg.CORBA.Bounds;
  52 import org.omg.CORBA.UNKNOWN;
  53 import org.omg.CORBA.INTERNAL;
  54 import org.omg.CORBA.NO_IMPLEMENT;
  55 import org.omg.CORBA.CompletionStatus;
  56 import org.omg.CORBA.WrongTransaction;
  57 
  58 import org.omg.CORBA.portable.ApplicationException ;
  59 import org.omg.CORBA.portable.RemarshalException ;
  60 import org.omg.CORBA.portable.InputStream ;
  61 import org.omg.CORBA.portable.OutputStream ;
  62 
  63 import com.sun.corba.se.spi.orb.ORB;
  64 import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
  65 import com.sun.corba.se.spi.logging.CORBALogDomains;
  66 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  67 import com.sun.corba.se.impl.corba.AsynchInvoke;
  68 
  69 public class RequestImpl
  70     extends Request
  71 {
  72     ///////////////////////////////////////////////////////////////////////////
  73     // data members
  74 
  75     protected org.omg.CORBA.Object _target;
  76     protected String             _opName;
  77     protected NVList             _arguments;
  78     protected ExceptionList      _exceptions;
  79     private NamedValue           _result;
  80     protected Environment        _env;
  81     private Context              _ctx;
  82     private ContextList          _ctxList;
  83     protected ORB                _orb;
  84     private ORBUtilSystemException _wrapper;
  85 
  86     // invocation-specific stuff
  87     protected boolean            _isOneWay      = false;
  88     private int[]                _paramCodes;
  89     private long[]               _paramLongs;
  90     private java.lang.Object[]   _paramObjects;
  91 
  92     // support for deferred invocations.
  93     // protected instead of private since it needs to be set by the
  94     // thread object doing the asynchronous invocation.
  95     protected boolean            gotResponse    = false;
  96 
  97     ///////////////////////////////////////////////////////////////////////////
  98     // constructor
  99 
 100     // REVISIT - used to be protected.  Now public so it can be
 101     // accessed from xgiop.
 102     public RequestImpl (ORB orb,
 103                         org.omg.CORBA.Object targetObject,
 104                         Context ctx,
 105                         String operationName,
 106                         NVList argumentList,
 107                         NamedValue resultContainer,
 108                         ExceptionList exceptionList,
 109                         ContextList ctxList)
 110     {
 111 
 112         // initialize the orb
 113         _orb    = orb;
 114         _wrapper = ORBUtilSystemException.get( orb,
 115             CORBALogDomains.OA_INVOCATION ) ;
 116 
 117         // initialize target, context and operation name
 118         _target     = targetObject;
 119         _ctx    = ctx;
 120         _opName = operationName;
 121 
 122         // initialize argument list if not passed in
 123         if (argumentList == null)
 124             _arguments = new NVListImpl(_orb);
 125         else
 126             _arguments = argumentList;
 127 
 128         // set result container.
 129         _result = resultContainer;
 130 
 131         // initialize exception list if not passed in
 132         if (exceptionList == null)
 133             _exceptions = new ExceptionListImpl();
 134         else
 135             _exceptions = exceptionList;
 136 
 137         // initialize context list if not passed in
 138         if (ctxList == null)
 139             _ctxList = new ContextListImpl(_orb);
 140         else
 141             _ctxList = ctxList;
 142 
 143         // initialize environment
 144         _env    = new EnvironmentImpl();
 145 
 146     }
 147 
 148     public org.omg.CORBA.Object target()
 149     {
 150         return _target;
 151     }
 152 
 153     public String operation()
 154     {
 155         return _opName;
 156     }
 157 
 158     public NVList arguments()
 159     {
 160         return _arguments;
 161     }
 162 
 163     public NamedValue result()
 164     {
 165         return _result;
 166     }
 167 
 168     public Environment env()
 169     {
 170         return _env;
 171     }
 172 
 173     public ExceptionList exceptions()
 174     {
 175         return _exceptions;
 176     }
 177 
 178     public ContextList contexts()
 179     {
 180         return _ctxList;
 181     }
 182 
 183     public synchronized Context ctx()
 184     {
 185         if (_ctx == null)
 186             _ctx = new ContextImpl(_orb);
 187         return _ctx;
 188     }
 189 
 190     public synchronized void ctx(Context newCtx)
 191     {
 192         _ctx = newCtx;
 193     }
 194 
 195     public synchronized Any add_in_arg()
 196     {
 197         return _arguments.add(org.omg.CORBA.ARG_IN.value).value();
 198     }
 199 
 200     public synchronized Any add_named_in_arg(String name)
 201     {
 202         return _arguments.add_item(name, org.omg.CORBA.ARG_IN.value).value();
 203     }
 204 
 205     public synchronized Any add_inout_arg()
 206     {
 207         return _arguments.add(org.omg.CORBA.ARG_INOUT.value).value();
 208     }
 209 
 210     public synchronized Any add_named_inout_arg(String name)
 211     {
 212         return _arguments.add_item(name, org.omg.CORBA.ARG_INOUT.value).value();
 213     }
 214 
 215     public synchronized Any add_out_arg()
 216     {
 217         return _arguments.add(org.omg.CORBA.ARG_OUT.value).value();
 218     }
 219 
 220     public synchronized Any add_named_out_arg(String name)
 221     {
 222         return _arguments.add_item(name, org.omg.CORBA.ARG_OUT.value).value();
 223     }
 224 
 225     public synchronized void set_return_type(TypeCode tc)
 226     {
 227         if (_result == null)
 228             _result = new NamedValueImpl(_orb);
 229         _result.value().type(tc);
 230     }
 231 
 232     public synchronized Any return_value()
 233     {
 234         if (_result == null)
 235             _result = new NamedValueImpl(_orb);
 236         return _result.value();
 237     }
 238 
 239     public synchronized void add_exception(TypeCode exceptionType)
 240     {
 241         _exceptions.add(exceptionType);
 242     }
 243 
 244     public synchronized void invoke()
 245     {
 246         doInvocation();
 247     }
 248 
 249     public synchronized void send_oneway()
 250     {
 251         _isOneWay = true;
 252         doInvocation();
 253     }
 254 
 255     public synchronized void send_deferred()
 256     {
 257         AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false);
 258         new Thread(null, invokeObject, "Async-Request-Invoker-Thread", 0, false).start();
 259     }
 260 
 261     public synchronized boolean poll_response()
 262     {
 263         // this method has to be synchronized even though it seems
 264         // "readonly" since the thread object doing the asynchronous
 265         // invocation can potentially update this variable in parallel.
 266         // updates are currently simply synchronized againt the request
 267         // object.
 268         return gotResponse;
 269     }
 270 
 271     public synchronized void get_response()
 272         throws org.omg.CORBA.WrongTransaction
 273     {
 274         while (gotResponse == false) {
 275             // release the lock. wait to be notified by the thread that is
 276             // doing the asynchronous invocation.
 277             try {
 278                 wait();
 279             }
 280             catch (InterruptedException e) {}
 281         }
 282     }
 283 
 284     ///////////////////////////////////////////////////////////////////////////
 285     // private helper methods
 286 
 287     /*
 288      * The doInvocation operation is where the real mechanics of
 289      * performing the request invocation is done.
 290      */
 291     protected void doInvocation()
 292     {
 293         org.omg.CORBA.portable.Delegate delegate = StubAdapter.getDelegate(
 294             _target ) ;
 295 
 296         // Initiate Client Portable Interceptors.  Inform the PIHandler that
 297         // this is a DII request so that it knows to ignore the second
 298         // inevitable call to initiateClientPIRequest in createRequest.
 299         // Also, save the RequestImpl object for later use.
 300         _orb.getPIHandler().initiateClientPIRequest( true );
 301         _orb.getPIHandler().setClientPIInfo( this );
 302 
 303         InputStream $in = null;
 304         try {
 305             OutputStream $out = delegate.request(null, _opName, !_isOneWay);
 306             // Marshal args
 307             try {
 308                 for (int i=0; i<_arguments.count() ; i++) {
 309                     NamedValue nv = _arguments.item(i);
 310                     switch (nv.flags()) {
 311                     case ARG_IN.value:
 312                         nv.value().write_value($out);
 313                         break;
 314                     case ARG_OUT.value:
 315                         break;
 316                     case ARG_INOUT.value:
 317                         nv.value().write_value($out);
 318                         break;
 319                     }
 320                 }
 321             } catch ( org.omg.CORBA.Bounds ex ) {
 322                 throw _wrapper.boundsErrorInDiiRequest( ex ) ;
 323             }
 324 
 325             $in = delegate.invoke(null, $out);
 326         } catch (ApplicationException e) {
 327             // REVISIT - minor code.
 328             // This is already handled in subcontract.
 329             // REVISIT - uncomment.
 330             //throw new INTERNAL();
 331         } catch (RemarshalException e) {
 332             doInvocation();
 333         } catch( SystemException ex ) {
 334             _env.exception(ex);
 335             // NOTE: The exception should not be thrown.
 336             // However, JDK 1.4 and earlier threw the exception,
 337             // so we keep the behavior to be compatible.
 338             throw ex;
 339         } finally {
 340             delegate.releaseReply(null, $in);
 341         }
 342     }
 343 
 344     // REVISIT -  make protected after development - so xgiop can get it.
 345     public void unmarshalReply(InputStream is)
 346     {
 347         // First unmarshal the return value if it is not void
 348         if ( _result != null ) {
 349             Any returnAny = _result.value();
 350             TypeCode returnType = returnAny.type();
 351             if ( returnType.kind().value() != TCKind._tk_void )
 352                 returnAny.read_value(is, returnType);
 353         }
 354 
 355         // Now unmarshal the out/inout args
 356         try {
 357             for ( int i=0; i<_arguments.count() ; i++) {
 358                 NamedValue nv = _arguments.item(i);
 359                 switch( nv.flags() ) {
 360                 case ARG_IN.value:
 361                     break;
 362                 case ARG_OUT.value:
 363                 case ARG_INOUT.value:
 364                     Any any = nv.value();
 365                     any.read_value(is, any.type());
 366                     break;
 367                 }
 368             }
 369         }
 370         catch ( org.omg.CORBA.Bounds ex ) {
 371             // Cannot happen since we only iterate till _arguments.count()
 372         }
 373     }
 374 }