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 32package com.sun.corba.se.impl.corba; 33 34import org.omg.CORBA.Any; 35import org.omg.CORBA.Context; 36import org.omg.CORBA.NamedValue; 37import org.omg.CORBA.NVList; 38import org.omg.CORBA.TypeCode; 39import org.omg.CORBA.TCKind; 40import org.omg.CORBA.ServerRequest; 41import org.omg.CORBA.Bounds; 42import org.omg.CORBA.portable.InputStream; 43import org.omg.CORBA.portable.OutputStream; 44import org.omg.CORBA.CompletionStatus; 45 46import com.sun.corba.se.spi.orb.ORB ; 47import com.sun.corba.se.spi.protocol.CorbaMessageMediator; 48 49import com.sun.corba.se.spi.logging.CORBALogDomains ; 50import com.sun.corba.se.impl.logging.ORBUtilSystemException ; 51 52public 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} 258