2 #include "tao/PI_Server/ServerRequestInfo.h"
4 #if (TAO_HAS_INTERCEPTORS == 1)
6 #include "tao/PortableServer/Root_POA.h"
7 #include "tao/PortableServer/Servant_Upcall.h"
8 #include "tao/PortableServer/Servant_Base.h"
10 #include "tao/TAO_Server_Request.h"
11 #include "tao/ORB_Core.h"
12 #include "tao/PolicyC.h"
13 #include "tao/AnyTypeCode/DynamicC.h"
14 #include "tao/ORB_Core.h"
15 #include "tao/Service_Context.h"
16 #include "tao/PI/RequestInfo_Util.h"
17 #include "tao/PI/PICurrent.h"
18 #include "tao/PI/PICurrent_Impl.h"
19 #include "tao/AnyTypeCode/ExceptionA.h"
21 #include "ace/OS_NS_string.h"
23 # if !defined (__ACE_INLINE__)
24 # include "tao/PI_Server/ServerRequestInfo.inl"
25 # endif /* !__ACE_INLINE__ */
27 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
30 TAO::ServerRequestInfo::request_id ()
32 // The request ID returned by this method need not correspond to the
33 // GIOP request ID sent with the client request. The request ID
34 // must be unique across all outstanding requests. To avoid locking
35 // overhead, the address of the TAO_ServerRequest object is used as
36 // the request ID. This guarantees that the request ID is unique.
38 // For 64-bit platforms, only the lower 32 bits are used. Hopefully
39 // that will be enough to ensure uniqueness.
43 // Note that we reinterpret_cast to an "unsigned long" instead of
44 // CORBA::ULong since we need to first cast to an integer large
45 // enough to hold an address to avoid compile-time warnings on some
48 if (sizeof (this) == 4) // 32 bit address
49 id
= static_cast <CORBA::ULong
> (
50 reinterpret_cast <ptrdiff_t>
51 (&(this->server_request_
)));
53 else if (sizeof (this) == 8) // 64 bit address -- use lower 32 bits
54 id
= static_cast <CORBA::ULong
> (
55 reinterpret_cast <ptrdiff_t>
56 (&(this->server_request_
)) & 0xFFFFFFFFu
);
59 // @@ Rather than fallback on the GIOP request ID, we should use
60 // an atomically incremented variable specific to the ORB, or
61 // perhaps specific to the process.
62 id
= this->server_request_
.request_id (); // Fallback
68 TAO::ServerRequestInfo::operation ()
70 return CORBA::string_dup (this->server_request_
.operation ());
73 Dynamic::ParameterList
*
74 TAO::ServerRequestInfo::arguments ()
78 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
81 // Generate the argument list on demand.
82 Dynamic::ParameterList
* const parameter_list
=
83 TAO_RequestInfo_Util::make_parameter_list ();
85 Dynamic::ParameterList_var safe_parameter_list
= parameter_list
;
87 // Return value is always generated as first TAO::Argument in
88 // skeleton. It shouldn't be included in the parameter list.
90 TAO::Argument
* const * const begin
= this->args_
+ 1;
91 TAO::Argument
* const * const end
= this->args_
+ this->nargs_
;
93 ACE_ASSERT (end
- begin
>= 0);
95 parameter_list
->length (static_cast<CORBA::ULong
> (end
- begin
));
98 for (TAO::Argument
* const * i
= begin
; i
!= end
; ++i
, ++p
)
100 // Insert the operation parameters into the
101 // Dynamic::ParameterList.
102 Dynamic::Parameter
& parameter
= (*parameter_list
)[p
];
103 parameter
.mode
= (*i
)->mode ();
104 // When we are in receive_request and have an out argument, then
105 // don't copy it, just let the any be empty with typecode tk_null
106 if ((this->server_request_
.pi_reply_status () != -1) ||
107 (this->server_request_
.pi_reply_status () == -1 &&
108 (*i
)->mode () != CORBA::PARAM_OUT
))
110 (*i
)->interceptor_value (¶meter
.argument
);
114 return safe_parameter_list
._retn ();
117 Dynamic::ExceptionList
*
118 TAO::ServerRequestInfo::exceptions ()
122 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
125 // Generate the exception list on demand.
126 Dynamic::ExceptionList
* const exception_list
=
127 TAO_RequestInfo_Util::make_exception_list ();
129 Dynamic::ExceptionList_var safe_exception_list
= exception_list
;
131 exception_list
->length (this->nexceptions_
);
133 CORBA::TypeCode_ptr
const * const begin
= this->exceptions_
;
134 CORBA::TypeCode_ptr
const * const end
=
135 this->exceptions_
+ this->nexceptions_
;
138 for (CORBA::TypeCode_ptr
const * i
= begin
; i
!= end
; ++i
, ++e
)
140 CORBA::TypeCode_ptr tcp_object
= *i
;
141 (*exception_list
)[e
] = tcp_object
;
144 return safe_exception_list
._retn ();
147 Dynamic::ContextList
*
148 TAO::ServerRequestInfo::contexts ()
150 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
153 Dynamic::RequestContext
*
154 TAO::ServerRequestInfo::operation_context ()
156 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
160 TAO::ServerRequestInfo::result ()
164 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
167 // Generate the result on demand.
168 static CORBA::Boolean
const tk_void_any
= true;
170 CORBA::Any
* result_any
= TAO_RequestInfo_Util::make_any (tk_void_any
);
172 CORBA::Any_var safe_result_any
= result_any
;
174 // Result is always first element in TAO::Argument array.
175 TAO::Argument
* const r
= this->args_
[0];
177 r
->interceptor_value (result_any
);
179 return safe_result_any
._retn ();
183 TAO::ServerRequestInfo::response_expected ()
185 return this->server_request_
.response_expected ();
189 TAO::ServerRequestInfo::sync_scope ()
191 if (this->server_request_
.sync_with_server ())
193 return Messaging::SYNC_WITH_SERVER
;
196 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
199 PortableInterceptor::ReplyStatus
200 TAO::ServerRequestInfo::reply_status ()
202 if (this->server_request_
.pi_reply_status () == -1)
204 // A reply hasn't been received yet.
205 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
208 return this->server_request_
.pi_reply_status ();
212 TAO::ServerRequestInfo::forward_reference ()
214 if (this->server_request_
.pi_reply_status () != PortableInterceptor::LOCATION_FORWARD
)
216 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
219 // TAO_ServerRequest::forward_location() already duplicates the
220 // object reference. There is no need to duplicate it here.
221 return this->server_request_
.forward_location ();
225 TAO::ServerRequestInfo::get_slot (PortableInterceptor::SlotId id
)
227 // Retrieve the total number of assigned slots from the PICurrent.
228 // No TSS access is incurred.
229 CORBA::Object_ptr pi_current_obj
=
230 this->server_request_
.orb_core ()->pi_current ();
232 TAO::PICurrent
*pi_current
=
233 dynamic_cast <TAO::PICurrent
*> (pi_current_obj
);
236 throw ::CORBA::INTERNAL ();
238 pi_current
->check_validity (id
);
240 // Retrieve the request scope PICurrent object.
241 TAO::PICurrent_Impl
*rsc
= this->server_request_
.rs_pi_current ();
243 return rsc
->get_slot (id
);
246 IOP::ServiceContext
*
247 TAO::ServerRequestInfo::get_request_service_context (IOP::ServiceId id
)
249 TAO_Service_Context
&service_context_list
=
250 this->server_request_
.request_service_context ();
252 return this->get_service_context_i (service_context_list
, id
);
255 IOP::ServiceContext
*
256 TAO::ServerRequestInfo::get_reply_service_context (IOP::ServiceId id
)
258 TAO_Service_Context
& service_context_list
=
259 this->server_request_
.reply_service_context ();
261 return this->get_service_context_i (service_context_list
, id
);
264 IOP::ServiceContext
*
265 TAO::ServerRequestInfo::get_service_context_i (
266 TAO_Service_Context
& service_context_list
,
269 IOP::ServiceContext_var service_context
;
271 if (service_context_list
.get_context (id
, service_context
.out ()) != 0)
274 return service_context
._retn ();
279 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID
| 26, CORBA::COMPLETED_NO
);
283 // Use at own risk. There is no way currently of extracting an
284 // exception from an Any. This method is in place just to be compliant
287 TAO::ServerRequestInfo::sending_exception ()
289 if (this->server_request_
.pi_reply_status () != PortableInterceptor::SYSTEM_EXCEPTION
290 && this->server_request_
.pi_reply_status () != PortableInterceptor::USER_EXCEPTION
)
292 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
295 // The spec says that if it is a user exception which cannot be
296 // inserted then the UNKNOWN exception should be thrown with minor
298 CORBA::Any
* temp
{};
300 ACE_NEW_THROW_EX (temp
,
303 CORBA::SystemException::_tao_minor_code (
306 CORBA::COMPLETED_NO
));
308 CORBA::Any_var caught_exception_var
= temp
;
310 if (this->server_request_
.caught_exception ())
312 (*temp
) <<= *(this->server_request_
.caught_exception ());
315 return caught_exception_var
._retn ();
319 TAO::ServerRequestInfo::server_id ()
321 if (this->servant_upcall_
)
323 return CORBA::string_dup (this->server_request_
.orb_core ()->server_id ());
326 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
330 TAO::ServerRequestInfo::orb_id ()
332 if (this->servant_upcall_
)
334 return CORBA::string_dup (this->server_request_
.orb_core ()->orbid ());
337 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
340 PortableInterceptor::AdapterName
*
341 TAO::ServerRequestInfo::adapter_name ()
343 // The adapter_name attribute defines a name for the object adapter
344 // that services requests for the invoked object. In the case of the
345 // POA, the adapter_name is the sequence of names from the root POA
346 // to the POA that services the request. The root POA is not named
348 if (this->servant_upcall_
)
350 return this->servant_upcall_
->poa ().adapter_name ();
353 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
356 PortableInterceptor::ObjectId
*
357 TAO::ServerRequestInfo::object_id ()
359 if (this->servant_upcall_
!= 0)
361 const PortableServer::ObjectId
&id
=
362 this->servant_upcall_
->user_id ();
364 PortableInterceptor::ObjectId
*tmp
{};
366 ACE_NEW_THROW_EX (tmp
,
367 PortableInterceptor::ObjectId
,
369 CORBA::SystemException::_tao_minor_code (
372 CORBA::COMPLETED_NO
));
374 PortableInterceptor::ObjectId_var obj_id
= tmp
;
376 // @@ It would be nice to avoid this copy. However, we can't be
377 // sure if the octet sequence will out live the POA from
378 // which the object ID is ultimately obtained. In the event
379 // the octet sequence does out live the POA, a copy is indeed
380 // necessary. Do a copy to be on the safe side. In any
381 // case, this is still faster than the
382 // PortableServer::Current::object_id() method since no TSS
383 // access is involved.
384 CORBA::ULong
const len
= id
.length ();
385 obj_id
->length (len
);
386 CORBA::Octet
*buffer
= obj_id
->get_buffer ();
387 ACE_OS::memcpy (buffer
, id
.get_buffer (), len
);
389 return obj_id
._retn ();
392 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
396 TAO::ServerRequestInfo::adapter_id ()
398 if (this->servant_upcall_
)
400 return this->servant_upcall_
->poa ().id ();
403 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
407 TAO::ServerRequestInfo::target_most_derived_interface ()
409 if (this->servant_upcall_
== 0)
411 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
414 PortableServer::Servant
const servant
= this->servant_upcall_
->servant ();
418 throw ::CORBA::NO_RESOURCES (CORBA::OMGVMCID
| 1, CORBA::COMPLETED_NO
);
421 return CORBA::string_dup (servant
->_interface_repository_id ());
425 TAO::ServerRequestInfo::get_server_policy (CORBA::PolicyType type
)
427 if (this->servant_upcall_
!= 0)
429 CORBA::Policy_var policy
=
430 this->servant_upcall_
->poa ().get_policy (type
);
432 if (!CORBA::is_nil (policy
.in ()))
434 return policy
._retn ();
438 // No policy matching the given PolicyType was found.
439 throw ::CORBA::INV_POLICY (CORBA::OMGVMCID
| 3, CORBA::COMPLETED_NO
);
443 // @@ Technically, we shouldn't be throwing this exception since
444 // this method should be valid in all server side request
445 // interception points.
446 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
450 TAO::ServerRequestInfo::set_slot (PortableInterceptor::SlotId id
,
451 const CORBA::Any
&data
)
453 // Retrieve the total number of assigned slots from the PICurrent
454 // object. No TSS access is incurred.
455 CORBA::Object_ptr pi_current_obj
=
456 this->server_request_
.orb_core ()->pi_current ();
458 TAO::PICurrent
*pi_current
=
459 dynamic_cast <TAO::PICurrent
*> (pi_current_obj
);
462 throw ::CORBA::INTERNAL ();
464 pi_current
->check_validity (id
);
466 // Retrieve the "request scope current" (RSC).
467 TAO::PICurrent_Impl
* rsc
= this->server_request_
.rs_pi_current ();
469 rsc
->set_slot (id
, data
);
473 TAO::ServerRequestInfo::target_is_a (const char * id
)
475 if (this->servant_upcall_
== 0)
477 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 14, CORBA::COMPLETED_NO
);
480 // Implemented in the generated skeleton.
481 PortableServer::Servant
const servant
= this->servant_upcall_
->servant ();
485 throw ::CORBA::NO_RESOURCES (CORBA::OMGVMCID
| 1, CORBA::COMPLETED_NO
);
488 return servant
->_is_a (id
);
492 TAO::ServerRequestInfo::add_reply_service_context (
493 const IOP::ServiceContext
& service_context
,
494 CORBA::Boolean replace
)
496 // Get the service context from the list
497 TAO_Service_Context
&service_context_list
=
498 this->server_request_
.reply_service_context ();
500 if (service_context_list
.set_context (service_context
, replace
) == 0)
502 throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID
| 15, CORBA::COMPLETED_NO
);
506 TAO_END_VERSIONED_NAMESPACE_DECL
508 #endif /* TAO_HAS_INTERCEPTORS == 1 */