Server_Request.cpp

Go to the documentation of this file.
00001 // $Id: Server_Request.cpp 80380 2008-01-07 13:11:49Z mcorino $
00002 
00003 // Implementation of the Dynamic Server Skeleton Interface.
00004 
00005 #include "tao/DynamicInterface/Server_Request.h"
00006 
00007 ACE_RCSID (DynamicInterface,
00008            Server_Request,
00009            "$Id: Server_Request.cpp 80380 2008-01-07 13:11:49Z mcorino $")
00010 
00011 #include "tao/DynamicInterface/DII_Arguments.h"
00012 #include "tao/DynamicInterface/Unknown_User_Exception.h"
00013 #include "tao/PortableServer/Collocated_Arguments_Converter.h"
00014 #include "tao/AnyTypeCode/NVList.h"
00015 #include "tao/GIOP_Utils.h"
00016 #include "tao/AnyTypeCode/Marshal.h"
00017 #include "tao/AnyTypeCode/TypeCode.h"
00018 #include "tao/AnyTypeCode/Any_Impl.h"
00019 #include "tao/operation_details.h"
00020 #include "tao/SystemException.h"
00021 
00022 #if !defined (__ACE_INLINE__)
00023 # include "tao/DynamicInterface/Server_Request.inl"
00024 #endif /* ! __ACE_INLINE__ */
00025 
00026 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00027 
00028 // Reference counting for DSI ServerRequest object.
00029 
00030 CORBA::ULong
00031 CORBA::ServerRequest::_incr_refcnt (void)
00032 {
00033   return ++this->refcount_;
00034 }
00035 
00036 CORBA::ULong
00037 CORBA::ServerRequest::_decr_refcnt (void)
00038 {
00039   CORBA::ULong const new_count = --this->refcount_;
00040 
00041   if (new_count == 0)
00042     delete this;
00043 
00044   return new_count;
00045 }
00046 
00047 CORBA::ServerRequest::ServerRequest (TAO_ServerRequest &orb_server_request)
00048   : lazy_evaluation_ (0),
00049     ctx_ (CORBA::Context::_nil ()),
00050     params_ (CORBA::NVList::_nil ()),
00051     retval_ (0),
00052     exception_ (0),
00053     refcount_ (1),
00054     orb_server_request_ (orb_server_request),
00055     sent_gateway_exception_ (false)
00056 {
00057   this->orb_server_request_.is_dsi ();
00058 }
00059 
00060 CORBA::ServerRequest::~ServerRequest (void)
00061 {
00062   if (this->params_ != 0)
00063     {
00064       ::CORBA::release (this->params_);
00065     }
00066 
00067   delete this->retval_;
00068   delete this->exception_;
00069 }
00070 
00071 // Unmarshal in/inout params, and set up to marshal the appropriate
00072 // inout/out/return values later on.
00073 void
00074 CORBA::ServerRequest::arguments (CORBA::NVList_ptr &list)
00075 {
00076   // arguments() must be called before either of these.
00077   if (this->params_ != 0 || this->exception_ != 0)
00078     {
00079       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 7, CORBA::COMPLETED_NO);
00080     }
00081 
00082   // In a collocated situation there will not be an incoming CDR stream 
00083   // in which case we can get the arguments from the 
00084   // operation_details using the 'collocated argument converter'.
00085   if (this->orb_server_request_.collocated ())
00086   {
00087     this->params_ = list;
00088     
00089     if (this->orb_server_request_.operation_details ()->cac () != 0)
00090       {
00091         TAO_OutputCDR output;
00092         this->orb_server_request_.operation_details ()->cac (
00093                 )->dsi_convert_request (this->orb_server_request_,
00094                                         output);
00095         
00096         TAO_InputCDR input(output);
00097         this->params_->_tao_decode (input, CORBA::ARG_IN | CORBA::ARG_INOUT);
00098       }    
00099   }
00100   else
00101   {
00102     // Save params for later use when marshaling the reply.
00103     this->params_ = list;
00104 
00105     this->params_->_tao_incoming_cdr (*this->orb_server_request_.incoming (),
00106                                       CORBA::ARG_IN | CORBA::ARG_INOUT,
00107                                       this->lazy_evaluation_);
00108 
00109     // Pass this alignment back to the TAO_ServerRequest.
00110     this->orb_server_request_.dsi_nvlist_align (
00111                                   this->params_->_tao_target_alignment ());
00112   }
00113 }
00114 
00115 // Store the result value.  There's either an exception, or a result,
00116 // but not both of them.  Results can be reported (at most once)
00117 // only after the parameter list has been provided (maybe empty).
00118 void
00119 CORBA::ServerRequest::set_result (const CORBA::Any &value
00120                                   )
00121 {
00122   // Setting a result when another result already exists or if an exception
00123   // exists or before the args have been processeed is an error.
00124   if (this->retval_ != 0 || this->exception_ != 0 || this->params_ == 0)
00125     {
00126       throw ::CORBA::BAD_INV_ORDER (CORBA::OMGVMCID | 8, CORBA::COMPLETED_NO);
00127     }
00128 
00129   ACE_NEW_THROW_EX (this->retval_,
00130                     CORBA::Any (value),
00131                     CORBA::NO_MEMORY ());
00132 }
00133 
00134   // NOTE: if "" is set, there has been a system exception,
00135   // and it will take precedence over exceptions reported using the
00136   // set_exception() mechanism of the ServerRequest, which we assume
00137   // the application writer will use to report only user exceptions.
00138   // If both types of exception happen on the same invocation, the user
00139   // exception will be lost.
00140 
00141 // Store the exception value.
00142 void
00143 CORBA::ServerRequest::set_exception (const CORBA::Any &value)
00144 {
00145   CORBA::TypeCode_var tc = value.type ();
00146 
00147   CORBA::TCKind const kind = tc->kind ();
00148 
00149   // set_exception() can be called at any time, but the Any arg MUST
00150   // contain an exception.
00151   if (kind != CORBA::tk_except)
00152     {
00153       throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 21, CORBA::COMPLETED_MAYBE);
00154     }
00155 
00156   ACE_NEW_THROW_EX (this->exception_,
00157                     CORBA::Any (value),
00158                     CORBA::NO_MEMORY ());
00159 
00160   this->orb_server_request_.reply_status (GIOP::USER_EXCEPTION);
00161 }
00162 
00163 // This method will be utilized by the DSI servant to marshal outgoing
00164 // parameters.
00165 void
00166 CORBA::ServerRequest::dsi_marshal (void)
00167 {
00168   // There was a user exception, no need to marshal any parameters.
00169   if (this->sent_gateway_exception_)
00170     {
00171       return;
00172     }
00173 
00174   // In a collocated situation there is no outgoing CDR stream.
00175   // So, in case of an exception we just raise the UnknownUserException
00176   // and for a regular reply we use the 'collocated argument converter'.
00177   if (this->orb_server_request_.collocated ())
00178   {
00179     if (this->orb_server_request_.reply_status () == GIOP::USER_EXCEPTION)
00180       {
00181         throw CORBA::UnknownUserException (*this->exception_);
00182       }
00183     else if (this->orb_server_request_.operation_details ()->cac () != 0)
00184       {
00185         TAO_OutputCDR output;
00186         // marshal the return value if any
00187         if (this->retval_ != 0)
00188           {
00189             this->retval_->impl ()->marshal_value (output);
00190           }
00191 
00192         // marshal the "inout" and "out" parameters.
00193         if (this->params_ != 0)
00194           {
00195             this->params_->_tao_encode (
00196                               output,
00197                               CORBA::ARG_INOUT | CORBA::ARG_OUT);
00198           }
00199         
00200         TAO_InputCDR input (output);
00201         // set reply parameters
00202         this->orb_server_request_.operation_details ()->cac (
00203                 )->dsi_convert_reply (this->orb_server_request_,
00204                                       input);
00205       }
00206   }
00207   else
00208   {
00209     if (this->orb_server_request_.reply_status () == GIOP::NO_EXCEPTION)
00210       {
00211         // In DSI, we can't rely on the skeleton to do this.
00212         if (this->retval_ == 0 && this->params_ == 0)
00213           {
00214           this->orb_server_request_.argument_flag (false);
00215           }
00216 
00217         this->orb_server_request_.init_reply ();
00218 
00219         // Send the return value, if any.
00220         if (this->retval_ != 0)
00221           {
00222             this->retval_->impl ()->marshal_value (
00223                                         *this->orb_server_request_.outgoing ());
00224           }
00225 
00226         // Send the "inout" and "out" parameters.
00227         if (this->params_ != 0)
00228           {
00229             this->params_->_tao_encode (
00230                               *this->orb_server_request_.outgoing (),
00231                               CORBA::ARG_INOUT | CORBA::ARG_OUT);
00232           }
00233       }
00234     else
00235       {
00236       // This defaults to true, but just to be safe...
00237       this->orb_server_request_.argument_flag (true);
00238 
00239         // Write the reply header to the ORB request's outgoing CDR stream.
00240         this->orb_server_request_.init_reply ();
00241 
00242         this->exception_->impl ()->marshal_value (
00243                                       *this->orb_server_request_.outgoing ());
00244       }
00245   }
00246 
00247   this->orb_server_request_.tao_send_reply ();
00248 }
00249 
00250 void
00251 CORBA::ServerRequest::gateway_exception_reply (ACE_CString &raw_exception)
00252 {
00253   // This defaults to 1, but just to be safe...
00254   this->orb_server_request_.argument_flag (true);
00255 
00256   // This reply path handles only user exceptions.
00257   this->orb_server_request_.reply_status (GIOP::USER_EXCEPTION);
00258 
00259   this->orb_server_request_.init_reply ();
00260 
00261   // We know nothing about this exception, so we marshal it as a block
00262   // of bytes. The outgoing stream's byte order has already been matched
00263   // to the original source of the reply.
00264   this->orb_server_request_.outgoing ()->write_octet_array (
00265       reinterpret_cast<const CORBA::Octet *> (raw_exception.fast_rep ()),
00266       static_cast<CORBA::ULong> (raw_exception.length () + ACE_CDR::MAX_ALIGNMENT)
00267     );
00268 
00269   // This will prevent the marshaling of any parameters into this reply.
00270   this->sent_gateway_exception_ = true;
00271 
00272   this->orb_server_request_.tao_send_reply ();
00273 }
00274 
00275 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:43:23 2010 for TAO_DynamicInterface by  doxygen 1.4.7