1. /*
  2. * @(#)ServerRequestImpl.java 1.59 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.internal.corba;
  16. import org.omg.CORBA.Any;
  17. import org.omg.CORBA.Context;
  18. import org.omg.CORBA.NamedValue;
  19. import org.omg.CORBA.NVList;
  20. import org.omg.CORBA.TypeCode;
  21. import org.omg.CORBA.TCKind;
  22. import org.omg.CORBA.ServerRequest;
  23. import org.omg.CORBA.SystemException;
  24. import org.omg.CORBA.NO_IMPLEMENT;
  25. import org.omg.CORBA.BAD_INV_ORDER;
  26. import org.omg.CORBA.BAD_PARAM;
  27. import org.omg.CORBA.MARSHAL;
  28. import org.omg.CORBA.Bounds;
  29. import org.omg.CORBA.portable.InputStream;
  30. import org.omg.CORBA.portable.OutputStream;
  31. import org.omg.CORBA.CompletionStatus;
  32. import com.sun.corba.se.internal.core.*;
  33. import com.sun.corba.se.internal.orbutil.MinorCodes;
  34. public class ServerRequestImpl extends ServerRequest {
  35. ///////////////////////////////////////////////////////////////////////////
  36. // data members
  37. private ORB _orb = null;
  38. private String _opName = null;
  39. private NVList _arguments = null;
  40. private Context _ctx = null;
  41. private InputStream _ins = null;
  42. // booleans to check for various operation invocation restrictions
  43. private boolean _paramsCalled = false;
  44. private boolean _resultSet = false;
  45. private boolean _exceptionSet = false;
  46. private Any _resultAny = null;
  47. private Any _exception = null;
  48. public ServerRequestImpl (com.sun.corba.se.internal.core.ServerRequest req, ORB orb) {
  49. _opName = req.getOperationName();
  50. _ins = (InputStream)req;
  51. _ctx = null; // if we support contexts, this would
  52. // presumably also be available on
  53. // the server invocation
  54. _orb = orb;
  55. }
  56. public String operation() {
  57. return _opName;
  58. }
  59. public void arguments(NVList args)
  60. {
  61. if ( _paramsCalled || _exceptionSet )
  62. throw new BAD_INV_ORDER();
  63. if ( args == null )
  64. throw new BAD_PARAM();
  65. _paramsCalled = true;
  66. NamedValue arg = null;
  67. for (int i=0; i < args.count() ; i++) {
  68. try {
  69. arg = args.item(i);
  70. }
  71. catch (Bounds e) {
  72. }
  73. try {
  74. if ((arg.flags() == org.omg.CORBA.ARG_IN.value) ||
  75. (arg.flags() == org.omg.CORBA.ARG_INOUT.value)) {
  76. // unmarshal the value into the Any
  77. arg.value().read_value(_ins, arg.value().type());
  78. }
  79. } catch ( Exception ex ) {
  80. throw new MARSHAL("Bad arguments NVList. Error while unmarshaling parameters");
  81. }
  82. }
  83. // hang on to the NVList for marshaling the result
  84. _arguments = args;
  85. _orb.setServerPIInfo( _arguments );
  86. _orb.invokeServerPIIntermediatePoint();
  87. }
  88. public void set_result(Any res) {
  89. // check for invocation restrictions
  90. if ( !_paramsCalled || _resultSet || _exceptionSet )
  91. throw new BAD_INV_ORDER();
  92. if ( res == null )
  93. throw new BAD_PARAM();
  94. _resultAny = res;
  95. _resultSet = true;
  96. // Notify portable interceptors of the result so that
  97. // ServerRequestInfo.result() functions as desired.
  98. _orb.setServerPIInfo( _resultAny );
  99. // actual marshaling of the reply msg header and params takes place
  100. // after the DSI returns control to the ORB.
  101. }
  102. public void set_exception(Any exc)
  103. {
  104. // except can be called by the DIR at any time (CORBA 2.2 section 6.3).
  105. if ( exc == null )
  106. throw new BAD_PARAM();
  107. // Ensure that the Any contains a SystemException or a
  108. // UserException. If the UserException is not a declared exception,
  109. // the client will get an UNKNOWN exception.
  110. TCKind kind = exc.type().kind();
  111. if ( kind != TCKind.tk_except )
  112. throw new BAD_PARAM();
  113. _exception = exc;
  114. // Inform Portable interceptors of the exception that was set
  115. // so sending_exception can return the right value.
  116. _orb.setServerPIExceptionInfo( _exception );
  117. // The user can only call arguments once and not at all after
  118. // set_exception. (internal flags ensure this). However, the user
  119. // can call set_exception multiple times. Therefore, we only
  120. // invoke receive_request the first time set_exception is
  121. // called (if they haven't already called arguments).
  122. if( !_exceptionSet && !_paramsCalled ) {
  123. // We need to invoke intermediate points here.
  124. _orb.invokeServerPIIntermediatePoint();
  125. }
  126. _exceptionSet = true;
  127. // actual marshaling of the reply msg header and exception takes place
  128. // after the DSI returns control to the ORB.
  129. }
  130. /** This is called from the ORB after the DynamicImplementation.invoke
  131. * returns. Here we set the result if result() has not already been called.
  132. * @return the exception if there is one (then ORB will not call
  133. * marshalReplyParams()) otherwise return null.
  134. */
  135. public Any checkResultCalled()
  136. {
  137. // Two things to be checked (CORBA 2.2 spec, section 6.3):
  138. // 1. Unless it calls set_exception(), the DIR must call arguments()
  139. // exactly once, even if the operation signature contains
  140. // no parameters.
  141. // 2. Unless set_exception() is called, if the invoked operation has a
  142. // non-void result type, set_result() must be called exactly once
  143. // before the DIR returns.
  144. if ( _paramsCalled && _resultSet ) // normal invocation return
  145. return null;
  146. else if ( _paramsCalled && !_resultSet && !_exceptionSet ) {
  147. try {
  148. // Neither a result nor an exception has been set.
  149. // Assume that the return type is void. If this is not so,
  150. // the client will throw a MARSHAL exception while
  151. // unmarshaling the return value.
  152. TypeCode result_tc = _orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_void);
  153. _resultAny = _orb.create_any();
  154. _resultAny.type(result_tc);
  155. _resultSet = true;
  156. return null;
  157. } catch ( Exception ex ) {
  158. throw new org.omg.CORBA.MARSHAL(MinorCodes.DSI_RESULT_EXCEPTION,
  159. CompletionStatus.COMPLETED_MAYBE);
  160. }
  161. }
  162. else if ( _exceptionSet )
  163. return _exception;
  164. else {
  165. // neither params() nor except() has been called.
  166. throw new BAD_INV_ORDER(MinorCodes.DSIMETHOD_NOTCALLED,
  167. CompletionStatus.COMPLETED_MAYBE);
  168. }
  169. }
  170. /** This is called from the ORB after the DynamicImplementation.invoke
  171. * returns. Here we marshal the return value and inout/out params.
  172. */
  173. public void marshalReplyParams(OutputStream os)
  174. {
  175. // marshal the operation return value
  176. _resultAny.write_value(os);
  177. // marshal the inouts/outs
  178. NamedValue arg = null;
  179. for (int i=0; i < _arguments.count() ; i++) {
  180. try {
  181. arg = _arguments.item(i);
  182. } catch (Bounds e) {}
  183. if ((arg.flags() == org.omg.CORBA.ARG_OUT.value) ||
  184. (arg.flags() == org.omg.CORBA.ARG_INOUT.value)) {
  185. arg.value().write_value(os);
  186. }
  187. }
  188. }
  189. public Context ctx()
  190. {
  191. if ( !_paramsCalled || _resultSet || _exceptionSet )
  192. throw new BAD_INV_ORDER();
  193. throw new NO_IMPLEMENT(MinorCodes.CONTEXT_NOT_IMPLEMENTED,
  194. CompletionStatus.COMPLETED_NO);
  195. }
  196. }