1 /*
   2  * Copyright (c) 1996, 2004, 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 import org.omg.CORBA.Any;
  35 import org.omg.CORBA.Context;
  36 import org.omg.CORBA.NamedValue;
  37 import org.omg.CORBA.NVList;
  38 import org.omg.CORBA.TypeCode;
  39 import org.omg.CORBA.TCKind;
  40 import org.omg.CORBA.ServerRequest;
  41 import org.omg.CORBA.Bounds;
  42 import org.omg.CORBA.portable.InputStream;
  43 import org.omg.CORBA.portable.OutputStream;
  44 import org.omg.CORBA.CompletionStatus;
  45 
  46 import com.sun.corba.se.spi.orb.ORB ;
  47 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
  48 
  49 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  50 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  51 
  52 public class ServerRequestImpl extends ServerRequest {
  53 
  54     ///////////////////////////////////////////////////////////////////////////
  55     // data members
  56 
  57     private ORB                  _orb           = null;
  58     private ORBUtilSystemException _wrapper     = null;
  59     private String               _opName        = null;
  60     private NVList               _arguments     = null;
  61     private Context              _ctx           = null;
  62     private InputStream          _ins           = null;
  63 
  64     // booleans to check for various operation invocation restrictions
  65     private boolean             _paramsCalled   = false;
  66     private boolean             _resultSet      = false;
  67     private boolean             _exceptionSet   = false;
  68     private Any                 _resultAny      = null;
  69     private Any                 _exception      = null;
  70 
  71 
  72     public ServerRequestImpl (CorbaMessageMediator req, ORB orb) {
  73         _opName = req.getOperationName();
  74         _ins    = (InputStream)req.getInputObject();
  75         _ctx    = null;         // if we support contexts, this would
  76                                 // presumably also  be available on
  77                                 // the server invocation
  78         _orb = orb;
  79         _wrapper = ORBUtilSystemException.get( orb,
  80             CORBALogDomains.OA_INVOCATION ) ;
  81     }
  82 
  83     public String operation() {
  84         return _opName;
  85     }
  86 
  87     public void arguments(NVList args)
  88     {
  89         if (_paramsCalled)
  90             throw _wrapper.argumentsCalledMultiple() ;
  91 
  92         if (_exceptionSet)
  93             throw _wrapper.argumentsCalledAfterException() ;
  94 
  95         if (args == null )
  96             throw _wrapper.argumentsCalledNullArgs() ;
  97 
  98         _paramsCalled = true;
  99 
 100         NamedValue arg = null;
 101         for (int i=0; i < args.count() ; i++) {
 102             try {
 103                 arg = args.item(i);
 104             } catch (Bounds e) {
 105                 throw _wrapper.boundsCannotOccur(e) ;
 106             }
 107 
 108             try {
 109                 if ((arg.flags() == org.omg.CORBA.ARG_IN.value) ||
 110                     (arg.flags() == org.omg.CORBA.ARG_INOUT.value)) {
 111                     // unmarshal the value into the Any
 112                     arg.value().read_value(_ins, arg.value().type());
 113                 }
 114             } catch ( Exception ex ) {
 115                 throw _wrapper.badArgumentsNvlist( ex ) ;
 116             }
 117         }
 118 
 119         // hang on to the NVList for marshaling the result
 120         _arguments = args;
 121 
 122         _orb.getPIHandler().setServerPIInfo( _arguments );
 123         _orb.getPIHandler().invokeServerPIIntermediatePoint();
 124     }
 125 
 126     public void set_result(Any res) {
 127         // check for invocation restrictions
 128         if (!_paramsCalled)
 129             throw _wrapper.argumentsNotCalled() ;
 130         if (_resultSet)
 131             throw _wrapper.setResultCalledMultiple() ;
 132         if (_exceptionSet)
 133             throw _wrapper.setResultAfterException() ;
 134         if ( res == null )
 135             throw _wrapper.setResultCalledNullArgs() ;
 136 
 137         _resultAny = res;
 138         _resultSet = true;
 139 
 140         // Notify portable interceptors of the result so that
 141         // ServerRequestInfo.result() functions as desired.
 142         _orb.getPIHandler().setServerPIInfo( _resultAny );
 143 
 144         // actual marshaling of the reply msg header and params takes place
 145         // after the DSI returns control to the ORB.
 146     }
 147 
 148     public void set_exception(Any exc)
 149     {
 150         // except can be called by the DIR at any time (CORBA 2.2 section 6.3).
 151 
 152         if ( exc == null )
 153             throw _wrapper.setExceptionCalledNullArgs() ;
 154 
 155         // Ensure that the Any contains a SystemException or a
 156         // UserException. If the UserException is not a declared exception,
 157         // the client will get an UNKNOWN exception.
 158         TCKind kind = exc.type().kind();
 159         if ( kind != TCKind.tk_except )
 160             throw _wrapper.setExceptionCalledBadType() ;
 161 
 162         _exception = exc;
 163 
 164         // Inform Portable interceptors of the exception that was set
 165         // so sending_exception can return the right value.
 166         _orb.getPIHandler().setServerPIExceptionInfo( _exception );
 167 
 168         // The user can only call arguments once and not at all after
 169         // set_exception.  (internal flags ensure this).  However, the user
 170         // can call set_exception multiple times.  Therefore, we only
 171         // invoke receive_request the first time set_exception is
 172         // called (if they haven't already called arguments).
 173         if( !_exceptionSet && !_paramsCalled ) {
 174             // We need to invoke intermediate points here.
 175             _orb.getPIHandler().invokeServerPIIntermediatePoint();
 176         }
 177 
 178         _exceptionSet = true;
 179 
 180         // actual marshaling of the reply msg header and exception takes place
 181         // after the DSI returns control to the ORB.
 182     }
 183 
 184 
 185     /** This is called from the ORB after the DynamicImplementation.invoke
 186      *  returns. Here we set the result if result() has not already been called.
 187      *  @return the exception if there is one (then ORB will not call
 188      *  marshalReplyParams()) otherwise return null.
 189      */
 190     public Any checkResultCalled()
 191     {
 192         // Two things to be checked (CORBA 2.2 spec, section 6.3):
 193         // 1. Unless it calls set_exception(), the DIR must call arguments()
 194         //    exactly once, even if the operation signature contains
 195         //    no parameters.
 196         // 2. Unless set_exception() is called, if the invoked operation has a
 197         //    non-void result type, set_result() must be called exactly once
 198         //    before the DIR returns.
 199 
 200         if ( _paramsCalled && _resultSet ) // normal invocation return
 201             return null;
 202         else if ( _paramsCalled && !_resultSet && !_exceptionSet ) {
 203             try {
 204                 // Neither a result nor an exception has been set.
 205                 // Assume that the return type is void. If this is not so,
 206                 // the client will throw a MARSHAL exception while
 207                 // unmarshaling the return value.
 208                 TypeCode result_tc = _orb.get_primitive_tc(
 209                     org.omg.CORBA.TCKind.tk_void);
 210                 _resultAny = _orb.create_any();
 211                 _resultAny.type(result_tc);
 212                 _resultSet = true;
 213 
 214                 return null;
 215             } catch ( Exception ex ) {
 216                 throw _wrapper.dsiResultException(
 217                     CompletionStatus.COMPLETED_MAYBE, ex ) ;
 218             }
 219         } else if ( _exceptionSet )
 220             return _exception;
 221         else {
 222             throw _wrapper.dsimethodNotcalled(
 223                 CompletionStatus.COMPLETED_MAYBE ) ;
 224         }
 225     }
 226 
 227     /** This is called from the ORB after the DynamicImplementation.invoke
 228      *  returns. Here we marshal the return value and inout/out params.
 229      */
 230     public void marshalReplyParams(OutputStream os)
 231     {
 232         // marshal the operation return value
 233         _resultAny.write_value(os);
 234 
 235         // marshal the inouts/outs
 236         NamedValue arg = null;
 237 
 238         for (int i=0; i < _arguments.count() ; i++) {
 239             try {
 240                 arg = _arguments.item(i);
 241             } catch (Bounds e) {}
 242 
 243             if ((arg.flags() == org.omg.CORBA.ARG_OUT.value) ||
 244                 (arg.flags() == org.omg.CORBA.ARG_INOUT.value)) {
 245                 arg.value().write_value(os);
 246             }
 247         }
 248     }
 249 
 250     public Context ctx()
 251     {
 252         if ( !_paramsCalled || _resultSet || _exceptionSet )
 253             throw _wrapper.contextCalledOutOfOrder() ;
 254 
 255         throw _wrapper.contextNotImplemented() ;
 256     }
 257 }