ServerRequestInfo.cpp

Go to the documentation of this file.
00001 // $Id: ServerRequestInfo.cpp 79705 2007-09-24 07:45:37Z johnnyw $
00002 
00003 #include "tao/PI_Server/ServerRequestInfo.h"
00004 
00005 #if (TAO_HAS_INTERCEPTORS == 1)
00006 
00007 ACE_RCSID (PI_Server,
00008            ServerRequestInfo,
00009            "$Id: ServerRequestInfo.cpp 79705 2007-09-24 07:45:37Z johnnyw $")
00010 
00011 #include "tao/PortableServer/Root_POA.h"
00012 #include "tao/PortableServer/Servant_Upcall.h"
00013 #include "tao/PortableServer/Servant_Base.h"
00014 
00015 #include "tao/TAO_Server_Request.h"
00016 #include "tao/ORB_Core.h"
00017 #include "tao/PolicyC.h"
00018 #include "tao/AnyTypeCode/DynamicC.h"
00019 #include "tao/ORB_Core.h"
00020 #include "tao/Service_Context.h"
00021 #include "tao/PI/RequestInfo_Util.h"
00022 #include "tao/PI/PICurrent.h"
00023 #include "tao/PI/PICurrent_Impl.h"
00024 #include "tao/AnyTypeCode/ExceptionA.h"
00025 
00026 #include "ace/OS_NS_string.h"
00027 
00028 # if !defined (__ACE_INLINE__)
00029 #   include "tao/PI_Server/ServerRequestInfo.inl"
00030 # endif /* !__ACE_INLINE__ */
00031 
00032 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00033 
00034 CORBA::ULong
00035 TAO::ServerRequestInfo::request_id (void)
00036 {
00037   // The request ID returned by this method need not correspond to the
00038   // GIOP request ID sent with the client request.  The request ID
00039   // must be unique across all outstanding requests.  To avoid locking
00040   // overhead, the address of the TAO_ServerRequest object is used as
00041   // the request ID.  This guarantees that the request ID is unique.
00042   //
00043   // For 64-bit platforms, only the lower 32 bits are used.  Hopefully
00044   // that will be enough to ensure uniqueness.
00045 
00046   CORBA::ULong id = 0;
00047 
00048   // Note that we reinterpret_cast to an "unsigned long" instead of
00049   // CORBA::ULong since we need to first cast to an integer large
00050   // enough to hold an address to avoid compile-time warnings on some
00051   // 64-bit platforms.
00052 
00053   if (sizeof (this) == 4)       // 32 bit address
00054     id = static_cast <CORBA::ULong> (
00055                      reinterpret_cast <ptrdiff_t>
00056                                       (&(this->server_request_)));
00057 
00058   else if (sizeof (this) == 8)  // 64 bit address -- use lower 32 bits
00059     id = static_cast <CORBA::ULong> (
00060                      reinterpret_cast <ptrdiff_t>
00061                                (&(this->server_request_)) & 0xFFFFFFFFu);
00062 
00063   else
00064     // @@ Rather than fallback on the GIOP request ID, we should use
00065     //    an atomically incremented variable specific to the ORB, or
00066     //    perhaps specific to the process.
00067     id = this->server_request_.request_id ();  // Fallback
00068 
00069   return id;
00070 }
00071 
00072 char *
00073 TAO::ServerRequestInfo::operation (void)
00074 {
00075   return CORBA::string_dup (this->server_request_.operation ());
00076 }
00077 
00078 Dynamic::ParameterList *
00079 TAO::ServerRequestInfo::arguments (void)
00080 {
00081   if (this->args_ == 0)
00082     {
00083       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00084     }
00085 
00086   // Generate the argument list on demand.
00087   Dynamic::ParameterList * const parameter_list =
00088     TAO_RequestInfo_Util::make_parameter_list ();
00089 
00090   Dynamic::ParameterList_var safe_parameter_list = parameter_list;
00091 
00092   // Return value is always generated as first TAO::Argument in
00093   // skeleton.  It shouldn't be included in the parameter list.
00094   // Skip it.
00095   TAO::Argument * const * const begin = this->args_ + 1;
00096   TAO::Argument * const * const end   = this->args_ + this->nargs_;
00097 
00098   ACE_ASSERT (end - begin >= 0);
00099 
00100   parameter_list->length (static_cast<CORBA::ULong> (end - begin));
00101 
00102   CORBA::ULong p = 0;
00103   for (TAO::Argument * const * i = begin; i != end; ++i, ++p)
00104     {
00105       // Insert the operation parameters into the
00106       // Dynamic::ParameterList.
00107       Dynamic::Parameter& parameter = (*parameter_list)[p];
00108       parameter.mode = (*i)->mode ();
00109       // When we are in receive_request and have an out argument, then
00110       // don't copy it, just let the any be empty with typecode tk_null
00111       if ((this->server_request_.pi_reply_status () != -1) ||
00112           (this->server_request_.pi_reply_status () == -1 &&
00113            (*i)->mode () != CORBA::PARAM_OUT))
00114         {
00115           (*i)->interceptor_value (&parameter.argument);
00116         }
00117     }
00118 
00119   return safe_parameter_list._retn ();
00120 }
00121 
00122 Dynamic::ExceptionList *
00123 TAO::ServerRequestInfo::exceptions (void)
00124 {
00125   if (this->args_ == 0)
00126     {
00127       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00128     }
00129 
00130   // Generate the exception list on demand.
00131   Dynamic::ExceptionList * const exception_list =
00132     TAO_RequestInfo_Util::make_exception_list ();
00133 
00134   Dynamic::ExceptionList_var safe_exception_list = exception_list;
00135 
00136   exception_list->length (this->nexceptions_);
00137 
00138   CORBA::TypeCode_ptr const * const begin = this->exceptions_;
00139   CORBA::TypeCode_ptr const * const end   =
00140     this->exceptions_ + this->nexceptions_;
00141 
00142   CORBA::ULong e = 0;
00143   for (CORBA::TypeCode_ptr const * i = begin; i != end; ++i, ++e)
00144     {
00145       CORBA::TypeCode_ptr tcp_object = *i;
00146       (*exception_list)[e] = tcp_object;
00147     }
00148 
00149   return safe_exception_list._retn ();
00150 }
00151 
00152 Dynamic::ContextList *
00153 TAO::ServerRequestInfo::contexts (void)
00154 {
00155   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00156 }
00157 
00158 Dynamic::RequestContext *
00159 TAO::ServerRequestInfo::operation_context (void)
00160 {
00161   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00162 }
00163 
00164 CORBA::Any *
00165 TAO::ServerRequestInfo::result (void)
00166 {
00167   if (this->args_ == 0)
00168     {
00169       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00170     }
00171 
00172   // Generate the result on demand.
00173   static CORBA::Boolean const tk_void_any = true;
00174 
00175   CORBA::Any * result_any =
00176     TAO_RequestInfo_Util::make_any (tk_void_any);
00177 
00178   CORBA::Any_var safe_result_any = result_any;
00179 
00180   // Result is always first element in TAO::Argument array.
00181   TAO::Argument * const r = this->args_[0];
00182 
00183   r->interceptor_value (result_any);
00184 
00185   return safe_result_any._retn ();
00186 }
00187 
00188 CORBA::Boolean
00189 TAO::ServerRequestInfo::response_expected (void)
00190 {
00191   return this->server_request_.response_expected ();
00192 }
00193 
00194 Messaging::SyncScope
00195 TAO::ServerRequestInfo::sync_scope (void)
00196 {
00197   if (this->server_request_.sync_with_server ())
00198     return Messaging::SYNC_WITH_SERVER;
00199 
00200   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00201 }
00202 
00203 PortableInterceptor::ReplyStatus
00204 TAO::ServerRequestInfo::reply_status (void)
00205 {
00206   if (this->server_request_.pi_reply_status () == -1)
00207     // A reply hasn't been received yet.
00208     throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00209 
00210   return this->server_request_.pi_reply_status ();
00211 }
00212 
00213 CORBA::Object_ptr
00214 TAO::ServerRequestInfo::forward_reference (void)
00215 {
00216   if (this->server_request_.pi_reply_status () != PortableInterceptor::LOCATION_FORWARD)
00217     throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00218 
00219   // TAO_ServerRequest::forward_location() already duplicates the
00220   // object reference.  There is no need to duplicate it here.
00221   return this->server_request_.forward_location ();
00222 }
00223 
00224 CORBA::Any *
00225 TAO::ServerRequestInfo::get_slot (PortableInterceptor::SlotId id)
00226 {
00227   // Retrieve the total number of assigned slots from the PICurrent.
00228   // No TSS access is incurred.
00229   CORBA::Object_ptr pi_current_obj =
00230     this->server_request_.orb_core ()->pi_current ();
00231 
00232   TAO::PICurrent *pi_current =
00233     dynamic_cast <TAO::PICurrent*> (pi_current_obj);
00234 
00235   if (pi_current == 0)
00236     throw ::CORBA::INTERNAL ();
00237 
00238   pi_current->check_validity (id);
00239 
00240   // Retrieve the request scope PICurrent object.
00241   TAO::PICurrent_Impl *rsc = this->server_request_.rs_pi_current ();
00242 
00243   return rsc->get_slot (id);
00244 
00245 }
00246 
00247 IOP::ServiceContext *
00248 TAO::ServerRequestInfo::get_request_service_context (IOP::ServiceId id)
00249 {
00250   TAO_Service_Context &service_context_list =
00251     this->server_request_.request_service_context ();
00252 
00253   return this->get_service_context_i (service_context_list, id);
00254 }
00255 
00256 IOP::ServiceContext *
00257 TAO::ServerRequestInfo::get_reply_service_context (IOP::ServiceId id)
00258 {
00259   TAO_Service_Context & service_context_list =
00260     this->server_request_.reply_service_context ();
00261 
00262   return this->get_service_context_i (service_context_list, id);
00263 }
00264 
00265 IOP::ServiceContext *
00266 TAO::ServerRequestInfo::get_service_context_i (
00267     TAO_Service_Context & service_context_list,
00268     IOP::ServiceId id)
00269 {
00270   IOP::ServiceContext_var service_context;
00271 
00272   if (service_context_list.get_context (id, service_context.out ()) != 0)
00273     {
00274       // Found.
00275       return service_context._retn ();
00276     }
00277   else
00278     {
00279       // Not found.
00280       throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 26, CORBA::COMPLETED_NO);
00281     }
00282 }
00283 
00284 // Use at own risk. There is no way currently of extracting an
00285 // exception from an Any. This method is in place just to be compliant
00286 // with the spec.
00287 CORBA::Any *
00288 TAO::ServerRequestInfo::sending_exception (void)
00289 {
00290   if (this->server_request_.pi_reply_status () != PortableInterceptor::SYSTEM_EXCEPTION
00291       && this->server_request_.pi_reply_status () != PortableInterceptor::USER_EXCEPTION)
00292     {
00293       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00294     }
00295 
00296   // The spec says that if it is a user exception which cannot be
00297   // inserted then the UNKNOWN exception should be thrown with minor
00298   // code 1.
00299 
00300   CORBA::Any * temp = 0;
00301 
00302   ACE_NEW_THROW_EX (temp,
00303                     CORBA::Any,
00304                     CORBA::NO_MEMORY (
00305                       CORBA::SystemException::_tao_minor_code (
00306                         TAO::VMCID,
00307                         ENOMEM),
00308                       CORBA::COMPLETED_NO));
00309 
00310   CORBA::Any_var caught_exception_var = temp;
00311 
00312   if (this->server_request_.caught_exception () != 0)
00313     (*temp) <<= *(this->server_request_.caught_exception ());
00314 
00315   return caught_exception_var._retn ();
00316 }
00317 
00318 char *
00319 TAO::ServerRequestInfo::server_id (void)
00320 {
00321   if (this->servant_upcall_ != 0)
00322     return
00323       CORBA::string_dup (this->server_request_.orb_core ()->server_id ());
00324 
00325   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00326 }
00327 
00328 char *
00329 TAO::ServerRequestInfo::orb_id (void)
00330 {
00331   if (this->servant_upcall_ != 0)
00332     return
00333       CORBA::string_dup (this->server_request_.orb_core ()->orbid ());
00334 
00335   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00336 }
00337 
00338 PortableInterceptor::AdapterName *
00339 TAO::ServerRequestInfo::adapter_name (void)
00340 {
00341   // The adapter_name attribute defines a name for the object adapter
00342   // that services requests for the invoked object. In the case of the
00343   // POA, the adapter_name is the sequence of names from the root POA
00344   // to the POA that services the request. The root POA is not named
00345   // in this sequence.
00346   if (this->servant_upcall_ != 0)
00347     return
00348       this->servant_upcall_->poa ().adapter_name ();
00349 
00350   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00351 }
00352 
00353 PortableInterceptor::ObjectId *
00354 TAO::ServerRequestInfo::object_id (void)
00355 {
00356   if (this->servant_upcall_ != 0)
00357     {
00358       const PortableServer::ObjectId &id =
00359         this->servant_upcall_->user_id ();
00360 
00361       PortableInterceptor::ObjectId *tmp = 0;
00362 
00363       ACE_NEW_THROW_EX (tmp,
00364                         PortableInterceptor::ObjectId,
00365                         CORBA::NO_MEMORY (
00366                           CORBA::SystemException::_tao_minor_code (
00367                             TAO::VMCID,
00368                             ENOMEM),
00369                           CORBA::COMPLETED_NO));
00370 
00371       PortableInterceptor::ObjectId_var obj_id = tmp;
00372 
00373       // @@ It would be nice to avoid this copy.  However, we can't be
00374       //    sure if the octet sequence will out live the POA from
00375       //    which the object ID is ultimately obtained.  In the event
00376       //    the octet sequence does out live the POA, a copy is indeed
00377       //    necessary.  Do a copy to be on the safe side.  In any
00378       //    case, this is still faster than the
00379       //    PortableServer::Current::object_id() method since no TSS
00380       //    access is involved.
00381       CORBA::ULong const len = id.length ();
00382       obj_id->length (len);
00383       CORBA::Octet *buffer = obj_id->get_buffer ();
00384       ACE_OS::memcpy (buffer, id.get_buffer (), len);
00385 
00386       return obj_id._retn ();
00387     }
00388 
00389   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00390 }
00391 
00392 CORBA::OctetSeq *
00393 TAO::ServerRequestInfo::adapter_id (void)
00394 {
00395   if (this->servant_upcall_ != 0)
00396     return this->servant_upcall_->poa ().id ();
00397 
00398   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00399 }
00400 
00401 char *
00402 TAO::ServerRequestInfo::target_most_derived_interface (void)
00403 {
00404   PortableServer::Servant const servant =
00405     (this->servant_upcall_ == 0
00406      ? 0
00407      : this->servant_upcall_->servant ());
00408 
00409   if (servant == 0)
00410     {
00411       throw ::CORBA::NO_RESOURCES (CORBA::OMGVMCID | 1, CORBA::COMPLETED_NO);
00412     }
00413 
00414   return CORBA::string_dup (servant->_interface_repository_id ());
00415 }
00416 
00417 CORBA::Policy_ptr
00418 TAO::ServerRequestInfo::get_server_policy (CORBA::PolicyType type)
00419 {
00420   if (this->servant_upcall_ != 0)
00421     {
00422       CORBA::Policy_var policy =
00423         this->servant_upcall_->poa ().get_policy (type);
00424 
00425       if (!CORBA::is_nil (policy.in ()))
00426         {
00427           return policy._retn ();
00428         }
00429       else
00430         {
00431           // No policy matching the given PolicyType was found.
00432           throw ::CORBA::INV_POLICY (CORBA::OMGVMCID | 3, CORBA::COMPLETED_NO);
00433         }
00434     }
00435 
00436   // @@ Technically, we shouldn't be throwing this exception since
00437   //    this method should be valid in all server side request
00438   //    interception points.
00439   throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 14, CORBA::COMPLETED_NO);
00440 }
00441 
00442 void
00443 TAO::ServerRequestInfo::set_slot (PortableInterceptor::SlotId id,
00444                                   const CORBA::Any &data)
00445 {
00446   // Retrieve the total number of assigned slots from the PICurrent
00447   // object.  No TSS access is incurred.
00448   CORBA::Object_ptr pi_current_obj =
00449     this->server_request_.orb_core ()->pi_current ();
00450 
00451   TAO::PICurrent *pi_current =
00452     dynamic_cast <TAO::PICurrent*> (pi_current_obj);
00453 
00454   if (pi_current == 0)
00455     throw ::CORBA::INTERNAL ();
00456 
00457   pi_current->check_validity (id);
00458 
00459   // Retrieve the "request scope current" (RSC).
00460   TAO::PICurrent_Impl * rsc = this->server_request_.rs_pi_current ();
00461 
00462   rsc->set_slot (id, data);
00463 }
00464 
00465 CORBA::Boolean
00466 TAO::ServerRequestInfo::target_is_a (const char * id)
00467 {
00468   // Implemented in the generated skeleton.
00469 
00470   PortableServer::Servant const servant =
00471     (this->servant_upcall_ == 0
00472      ? 0
00473      : this->servant_upcall_->servant ());
00474 
00475   if (servant == 0)
00476     {
00477       throw ::CORBA::NO_RESOURCES (CORBA::OMGVMCID | 1, CORBA::COMPLETED_NO);
00478     }
00479 
00480   return servant->_is_a (id);
00481 }
00482 
00483 void
00484 TAO::ServerRequestInfo::add_reply_service_context (
00485     const IOP::ServiceContext & service_context,
00486     CORBA::Boolean replace)
00487 {
00488   // Get the service context from the list
00489   TAO_Service_Context &service_context_list =
00490     this->server_request_.reply_service_context ();
00491 
00492   if (service_context_list.set_context (service_context, replace) == 0)
00493     {
00494       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 15, CORBA::COMPLETED_NO);
00495     }
00496 }
00497 
00498 TAO_END_VERSIONED_NAMESPACE_DECL
00499 
00500 #endif  /* TAO_HAS_INTERCEPTORS == 1 */

Generated on Tue Feb 2 17:42:14 2010 for TAO_PI_Server by  doxygen 1.4.7