//============================================================================= /** * @file Forwarder.cpp * * @brief Definition of ImR_DSI_Forwarder * * @author Phil Mesnier */ //============================================================================= #include "orbsvcs/Log_Macros.h" #include "Forwarder.h" #include "ImR_Locator_i.h" #include "tao/ORB.h" #include "tao/Object_KeyC.h" #include "tao/ORB_Constants.h" #include "tao/PortableServer/PortableServer.h" #include "tao/PortableServer/POA_Current_Impl.h" #include "tao/PortableServer/POA_Current.h" #include "tao/TAO_Server_Request.h" #include "tao/DynamicInterface/Request.h" #include "tao/DynamicInterface/Server_Request.h" #include "tao/DynamicInterface/AMH_DSI_Response_Handler.h" #include "tao/Messaging/AMH_Response_Handler.h" ImR_DSI_Forwarder::ImR_DSI_Forwarder (ImR_Locator_i& imr_impl) : locator_ (imr_impl) , orb_ (0) { } ImR_DSI_Forwarder::~ImR_DSI_Forwarder (void) { } void ImR_DSI_Forwarder::init (CORBA::ORB_ptr orb) { ACE_ASSERT (! CORBA::is_nil(orb)); this->orb_ = orb; try { CORBA::Object_var tmp = orb->resolve_initial_references ("POACurrent"); this->poa_current_var_ = PortableServer::Current::_narrow (tmp.in ()); } catch (const CORBA::Exception&) { } ACE_ASSERT (!CORBA::is_nil (this->poa_current_var_.in ())); } void ImR_DSI_Forwarder::_dispatch (TAO_ServerRequest &request, TAO::Portable_Server::Servant_Upcall * /*context */ ) { // No need to do any of this if the client isn't waiting. if (request.response_expected ()) { if (!CORBA::is_nil (request.forward_location ())) { request.init_reply (); request.tao_send_reply (); // No need to invoke in this case. return; } } // Create DSI request object. CORBA::ServerRequest *dsi_request = 0; ACE_NEW (dsi_request, CORBA::ServerRequest (request)); try { TAO_AMH_DSI_Response_Handler_ptr rhp; ACE_NEW (rhp, TAO_AMH_DSI_Response_Handler(request)); TAO_AMH_DSI_Response_Handler_var rh(rhp); rh->init (request, 0); // Delegate to user. this->invoke (dsi_request, rh.in()); } catch (const CORBA::Exception& ex) { // Only if the client is waiting. if (request.response_expected () && !request.sync_with_server ()) { request.tao_send_reply_exception (ex); } } CORBA::release (dsi_request); } void ImR_DSI_Forwarder::invoke (CORBA::ServerRequest_ptr ) { // unused method, only asynch invocations are used } char * ImR_DSI_Forwarder::_primary_interface (const PortableServer::ObjectId&, PortableServer::POA_ptr) { return CORBA::string_dup ("IDL:Object:1.0"); } void ImR_DSI_Forwarder::invoke (CORBA::ServerRequest_ptr request, TAO_AMH_DSI_Response_Handler_ptr resp) { bool is_oneway = !(request->_tao_server_request().response_expected() || request->_tao_server_request().sync_with_server()); if (is_oneway) { return; // nothing else to do, the client isn't waiting so no forwarding // will happen. } PortableServer::POA_var poa = this->poa_current_var_->get_POA(); PortableServer::ObjectId_var oid = this->poa_current_var_->get_object_id (); CORBA::String_var server_name = poa->the_name(); CORBA::String_var key_str; // Unlike POA Current, this implementation cannot be cached. TAO::Portable_Server::POA_Current* tao_current = dynamic_cast (this->poa_current_var_.in ()); ACE_ASSERT(tao_current != 0); TAO::Portable_Server::POA_Current_Impl* impl = tao_current->implementation (); TAO::ObjectKey::encode_sequence_to_string (key_str.out (), impl->object_key ()); ImR_DSI_ResponseHandler * rh = 0; ACE_NEW (rh, ImR_DSI_ResponseHandler(key_str.in(), this->locator_.debug() > 0 ? server_name.in() : "", this->orb_, resp)); this->locator_.activate_server_by_name (server_name.in(), false, rh); } void ImR_DSI_Forwarder::invoke_get_interface(CORBA::ServerRequest_ptr ) { // no impl } void ImR_DSI_Forwarder::invoke_primary_interface(CORBA::ServerRequest_ptr ) { // no impl } //-------------------------------------------------------------------- ImR_DSI_ResponseHandler::ImR_DSI_ResponseHandler (const char *key, const char *server_name, CORBA::ORB_ptr orb, TAO_AMH_DSI_Response_Handler_ptr resp) :key_str_ (key), server_name_ (server_name), orb_(CORBA::ORB::_duplicate (orb)), resp_ (TAO_AMH_DSI_Response_Handler::_duplicate (resp)) { } ImR_DSI_ResponseHandler::~ImR_DSI_ResponseHandler (void) { } void ImR_DSI_ResponseHandler::send_ior (const char *pior) { ACE_CString ior = pior; // Check that the returned ior is the expected partial ior with // missing ObjectKey. if (ior.find ("corbaloc:") == 0 && ior[ior.length () -1] == '/') { ior += this->key_str_.in(); CORBA::Object_var forward_obj = this->orb_->string_to_object (ior.c_str ()); if (!CORBA::is_nil (forward_obj.in ())) { this->resp_->invoke_location_forward(forward_obj.in(), false); delete this; return; } else { ORBSVCS_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) ImR_DSI_ResponseHandler::send_ior (): Forward_to ") ACE_TEXT ("reference is nil\n"))); } } else { ORBSVCS_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) ImR_DSI_ResponseHandler::send_ior (): Invalid corbaloc ior for key <%C> server_name <%C> IOR <%C>\n"), key_str_.in (), server_name_.in (), pior)); } this->invoke_excep_i (new CORBA::OBJECT_NOT_EXIST (CORBA::SystemException::_tao_minor_code ( TAO_IMPLREPO_MINOR_CODE, 0), CORBA::COMPLETED_NO)); } void ImR_DSI_ResponseHandler::invoke_excep_i (CORBA::Exception *ex) { TAO_AMH_DSI_Exception_Holder h(ex); this->resp_->invoke_excep(&h); delete this; } void ImR_DSI_ResponseHandler::send_exception (CORBA::Exception *ex) { //discard the exception, always throw a transient: delete ex; this->invoke_excep_i (new CORBA::TRANSIENT (CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), CORBA::COMPLETED_NO)); }