1 // Implementation of the Dynamic Server Skeleton Interface.
3 #include "tao/DynamicInterface/Server_Request.h"
4 #include "tao/DynamicInterface/DII_Arguments.h"
5 #include "tao/DynamicInterface/Unknown_User_Exception.h"
6 #include "tao/PortableServer/Collocated_Arguments_Converter.h"
7 #include "tao/AnyTypeCode/NVList.h"
8 #include "tao/GIOP_Utils.h"
9 #include "tao/AnyTypeCode/Marshal.h"
10 #include "tao/AnyTypeCode/TypeCode.h"
11 #include "tao/AnyTypeCode/Any_Impl.h"
12 #include "tao/operation_details.h"
13 #include "tao/SystemException.h"
15 #if !defined (__ACE_INLINE__)
16 # include "tao/DynamicInterface/Server_Request.inl"
17 #endif /* ! __ACE_INLINE__ */
19 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
21 // Reference counting for DSI ServerRequest object.
23 CORBA::ServerRequest::_incr_refcount ()
25 return ++this->refcount_
;
29 CORBA::ServerRequest::_decr_refcount ()
31 CORBA::ULong
const new_count
= --this->refcount_
;
39 CORBA::ServerRequest::ServerRequest (TAO_ServerRequest
&orb_server_request
)
40 : lazy_evaluation_ (false),
41 ctx_ (CORBA::Context::_nil ()),
42 params_ (CORBA::NVList::_nil ()),
46 orb_server_request_ (orb_server_request
),
47 sent_gateway_exception_ (false)
49 this->orb_server_request_
.is_dsi ();
52 CORBA::ServerRequest::~ServerRequest ()
54 if (this->params_
!= 0)
56 ::CORBA::release (this->params_
);
60 delete this->exception_
;
63 // Unmarshal in/inout params, and set up to marshal the appropriate
64 // inout/out/return values later on.
66 CORBA::ServerRequest::arguments (CORBA::NVList_ptr
&list
)
68 // arguments() must be called before either of these.
69 if (this->params_
!= 0 || this->exception_
!= 0)
71 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 7, CORBA::COMPLETED_NO
);
74 // In a collocated situation there will not be an incoming CDR stream
75 // in which case we can get the arguments from the
76 // operation_details using the 'collocated argument converter'.
77 if (this->orb_server_request_
.collocated ())
81 if (this->orb_server_request_
.operation_details ()->cac () != 0)
84 this->orb_server_request_
.operation_details ()->cac (
85 )->dsi_convert_request (this->orb_server_request_
,
88 TAO_InputCDR
input(output
);
89 this->params_
->_tao_decode (input
, CORBA::ARG_IN
| CORBA::ARG_INOUT
);
94 // Save params for later use when marshaling the reply.
97 // in the case of a GIOP::LocateRequest there is no incoming CDR stream
98 // so skip any attempt to decode arguments (now or later)
99 if (this->orb_server_request_
.incoming () != 0)
101 this->params_
->_tao_incoming_cdr (*this->orb_server_request_
.incoming (),
102 CORBA::ARG_IN
| CORBA::ARG_INOUT
,
103 this->lazy_evaluation_
);
105 // Pass this alignment back to the TAO_ServerRequest.
106 this->orb_server_request_
.dsi_nvlist_align (
107 this->params_
->_tao_target_alignment ());
112 // Store the result value. There's either an exception, or a result,
113 // but not both of them. Results can be reported (at most once)
114 // only after the parameter list has been provided (maybe empty).
116 CORBA::ServerRequest::set_result (const CORBA::Any
&value
)
118 // Setting a result when another result already exists or if an exception
119 // exists or before the args have been processed is an error.
120 if (this->retval_
!= 0 || this->exception_
!= 0 || this->params_
== 0)
122 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 8, CORBA::COMPLETED_NO
);
125 ACE_NEW_THROW_EX (this->retval_
,
127 CORBA::NO_MEMORY ());
130 // NOTE: if "" is set, there has been a system exception,
131 // and it will take precedence over exceptions reported using the
132 // set_exception() mechanism of the ServerRequest, which we assume
133 // the application writer will use to report only user exceptions.
134 // If both types of exception happen on the same invocation, the user
135 // exception will be lost.
137 // Store the exception value.
139 CORBA::ServerRequest::set_exception (const CORBA::Any
&value
)
141 CORBA::TypeCode_var tc
= value
.type ();
143 CORBA::TCKind
const kind
= tc
->kind ();
145 // set_exception() can be called at any time, but the Any arg MUST
146 // contain an exception.
147 if (kind
!= CORBA::tk_except
)
149 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID
| 21, CORBA::COMPLETED_MAYBE
);
152 ACE_NEW_THROW_EX (this->exception_
,
154 CORBA::NO_MEMORY ());
156 this->orb_server_request_
.reply_status (GIOP::USER_EXCEPTION
);
159 // This method will be utilized by the DSI servant to marshal outgoing
162 CORBA::ServerRequest::dsi_marshal ()
164 // There was a user exception, no need to marshal any parameters.
165 if (this->sent_gateway_exception_
)
170 // In a collocated situation there is no outgoing CDR stream.
171 // So, in case of an exception we just raise the UnknownUserException
172 // and for a regular reply we use the 'collocated argument converter'.
173 if (this->orb_server_request_
.collocated ())
175 if (this->orb_server_request_
.reply_status () == GIOP::USER_EXCEPTION
)
177 throw CORBA::UnknownUserException (*this->exception_
);
179 else if (this->orb_server_request_
.operation_details ()->cac () != 0)
181 TAO_OutputCDR output
;
182 // marshal the return value if any
183 if (this->retval_
!= 0)
185 this->retval_
->impl ()->marshal_value (output
);
188 // marshal the "inout" and "out" parameters.
189 if (this->params_
!= 0)
191 this->params_
->_tao_encode (
193 CORBA::ARG_INOUT
| CORBA::ARG_OUT
);
196 TAO_InputCDR
input (output
);
197 // set reply parameters
198 this->orb_server_request_
.operation_details ()->cac (
199 )->dsi_convert_reply (this->orb_server_request_
,
205 if (this->orb_server_request_
.reply_status () == GIOP::NO_EXCEPTION
)
207 // In DSI, we can't rely on the skeleton to do this.
208 if (this->retval_
== 0 && this->params_
== 0)
210 this->orb_server_request_
.argument_flag (false);
213 this->orb_server_request_
.init_reply ();
215 // Send the return value, if any.
216 if (this->retval_
!= 0)
218 this->retval_
->impl ()->marshal_value (
219 *this->orb_server_request_
.outgoing ());
222 // Send the "inout" and "out" parameters.
223 if (this->params_
!= 0)
225 this->params_
->_tao_encode (
226 *this->orb_server_request_
.outgoing (),
227 CORBA::ARG_INOUT
| CORBA::ARG_OUT
);
232 // This defaults to true, but just to be safe...
233 this->orb_server_request_
.argument_flag (true);
235 // Write the reply header to the ORB request's outgoing CDR stream.
236 this->orb_server_request_
.init_reply ();
238 this->exception_
->impl ()->marshal_value (
239 *this->orb_server_request_
.outgoing ());
243 // in case a deferred_reply is specified (like for GIOP::LocateRequest)
244 // do not send a reply here
245 if (!this->orb_server_request_
.deferred_reply ())
247 this->orb_server_request_
.tao_send_reply ();
252 CORBA::ServerRequest::gateway_exception_reply (ACE_CString
&raw_exception
)
254 // This defaults to 1, but just to be safe...
255 this->orb_server_request_
.argument_flag (true);
257 // This reply path handles only user exceptions.
258 this->orb_server_request_
.reply_status (GIOP::USER_EXCEPTION
);
260 this->orb_server_request_
.init_reply ();
262 // We know nothing about this exception, so we marshal it as a block
263 // of bytes. The outgoing stream's byte order has already been matched
264 // to the original source of the reply.
265 this->orb_server_request_
.outgoing ()->write_octet_array (
266 reinterpret_cast<const CORBA::Octet
*> (raw_exception
.fast_rep ()),
267 static_cast<CORBA::ULong
> (raw_exception
.length () + ACE_CDR::MAX_ALIGNMENT
));
269 // This will prevent the marshaling of any parameters into this reply.
270 this->sent_gateway_exception_
= true;
272 this->orb_server_request_
.tao_send_reply ();
275 TAO_END_VERSIONED_NAMESPACE_DECL