diff options
Diffstat (limited to 'TAO/tao/PortableServer/POA.cpp')
-rw-r--r-- | TAO/tao/PortableServer/POA.cpp | 4273 |
1 files changed, 4273 insertions, 0 deletions
diff --git a/TAO/tao/PortableServer/POA.cpp b/TAO/tao/PortableServer/POA.cpp new file mode 100644 index 00000000000..01850a01571 --- /dev/null +++ b/TAO/tao/PortableServer/POA.cpp @@ -0,0 +1,4273 @@ +// @(#) $Id$ + +#include "POA.h" +#include "Collocated_Object.h" + +// +// ImplRepo related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) +# include "ImplRepoS.h" +# include "ImplRepoC.h" +#endif /* TAO_HAS_MINIMUM_CORBA */ + +#include "tao/ORB_Core.h" +#include "tao/ORB.h" +#include "tao/Server_Strategy_Factory.h" +#include "tao/Environment.h" +#include "tao/Exception.h" +#include "tao/Stub.h" +#include "tao/debug.h" + +#include "tao/RT_Policy_i.h" +#include "tao/Acceptor_Filter.h" + +// auto_ptr class +#include "ace/Auto_Ptr.h" + +// +// ImplRepo related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) + +// This is to remove "inherits via dominance" warnings from MSVC. +// MSVC is being a little too paranoid. +#if defined(_MSC_VER) +#if (_MSC_VER >= 1200) +#pragma warning(push) +#endif /* _MSC_VER >= 1200 */ +#pragma warning(disable:4250) +#endif /* _MSC_VER */ + +// @@ Darrell: could you move this to some other file? It is kind of +// ugly around here. Also: we probably want this "optional", +// i.e. some kind of hook that creates this object only when IMR is +// enabled, we should talk about it. +class ServerObject_i + : public POA_ImplementationRepository::ServerObject, + public PortableServer::RefCountServantBase +{ + // = TITLE + // IMR Server Object Implementation + // + // = DESCRIPTION + // Implementation Repository uses this to communicate with the IMR + // registered server. +public: + ServerObject_i (CORBA::ORB_ptr orb) + : orb_ (orb) {} + + virtual void ping (CORBA::Environment &) + ACE_THROW_SPEC (()) + { + } + + virtual void shutdown (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC (()) + { + this->orb_->shutdown (0, ACE_TRY_ENV); + } +private: + CORBA::ORB_ptr orb_; +}; + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +#pragma warning(pop) +#endif /* _MSC_VER */ + +#endif /* TAO_HAS_MINIMUM_CORBA */ + + +// Forwarding Servant class +#include "Forwarding_Servant.h" + +#if !defined (__ACE_INLINE__) +# include "POA.i" +#endif /* ! __ACE_INLINE__ */ + +ACE_RCSID(tao, POA, "$Id$") + +#if (TAO_NO_IOR_TABLE == 0) + // This is the TAO_Object_key-prefix that is appended to all TAO Object keys. + // It's an array of octets representing ^t^a^o/0 in octal. + CORBA::Octet +TAO_POA::objectkey_prefix [TAO_POA::TAO_OBJECTKEY_PREFIX_SIZE] = { + 024, // octal for ^t + 001, // octal for ^a + 017, // octal for ^o + 000 +}; +#endif /* TAO_NO_IOR_TABLE */ + +TAO_POA::TAO_POA (const TAO_POA::String &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policies &policies, + TAO_POA *parent, + ACE_Lock &lock, + ACE_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter, + CORBA::Environment &ACE_TRY_ENV) + : name_ (name), + poa_manager_ (poa_manager), + policies_ (policies), + parent_ (parent), + active_object_map_ (0), + +#if (TAO_HAS_MINIMUM_POA == 0) + + adapter_activator_ (), + servant_activator_ (), + servant_locator_ (), + default_servant_ (), + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + // + // ImplRepo related. + // +#if (TAO_HAS_MINIMUM_CORBA == 0) + + server_object_ (0), + use_imr_ (1), + +#endif /* TAO_HAS_MINIMUM_CORBA */ + + children_ (), + lock_ (lock), + persistent_ (policies.lifespan () == PortableServer::PERSISTENT), + system_id_ (policies.id_assignment () == PortableServer::SYSTEM_ID), + creation_time_ (ACE_OS::gettimeofday ()), + orb_core_ (orb_core), + object_adapter_ (object_adapter), + cleanup_in_progress_ (0), + etherealize_objects_ (1), + outstanding_requests_ (0), + outstanding_requests_condition_ (thread_lock), + wait_for_completion_pending_ (0), + waiting_destruction_ (0), + servant_deactivation_condition_ (thread_lock), + waiting_servant_deactivation_ (0) +{ + // Set the folded name of this POA. + this->set_folded_name (); + + // Create the active object map. + TAO_Active_Object_Map *active_object_map = 0; + ACE_NEW_THROW_EX (active_object_map, + TAO_Active_Object_Map (!this->system_id (), + this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID, + this->persistent (), + this->orb_core_.server_factory ()->active_object_map_creation_parameters (), + ACE_TRY_ENV), + CORBA::NO_MEMORY ()); + + // Give ownership of the new map to the auto pointer. Note, that it + // is important for the auto pointer to take ownership before + // checking for exception since we may need to delete the new map. + auto_ptr<TAO_Active_Object_Map> new_active_object_map (active_object_map); + + // Check for exception in construction of the active object map. + ACE_CHECK; + + // Register self with manager. + int result = this->poa_manager_.register_poa (this); + if (result != 0) + { + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } + + // Add self to Object Adapter class. + result = this->object_adapter ().bind_poa (this->folded_name_, + this, + this->system_name_.out ()); + if (result != 0) + { + // Remove from POA Manager in case of errors. No checks of + // further errors... + this->poa_manager_.remove_poa (this); + + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } + + // Finally everything is fine. Make sure to take ownership away + // from the auto pointer. + this->active_object_map_ = new_active_object_map.release (); + +// +// ImplRepo related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) + if (this->policies_.lifespan () == PortableServer::PERSISTENT) + { + int temp = this->use_imr_; + this->use_imr_ = 0; + this->imr_notify_startup (ACE_TRY_ENV); + ACE_CHECK; + this->use_imr_ = temp; + } + +#endif /* TAO_HAS_MINIMUM_CORBA */ +} + +TAO_POA::~TAO_POA (void) +{ +} + +void +TAO_POA::complete_destruction_i (CORBA::Environment &ACE_TRY_ENV) +{ + // Delete the active object map. + delete this->active_object_map_; + + // Remove POA from the POAManager. + int result = this->poa_manager_.remove_poa (this); + if (result != 0) + ACE_THROW (CORBA::OBJ_ADAPTER ()); + + // Remove POA from the Object Adapter. + result = this->object_adapter ().unbind_poa (this, + this->folded_name_, + this->system_name_.in ()); + if (result != 0) + ACE_THROW (CORBA::OBJ_ADAPTER ()); + + // Forced cleanup. The new memory management scheme is evil and can + // lead to reference deadlock, i.e., POA holds object A, but POA + // cannot die because object A hold POA. + { + // A recursive thread lock without using a recursive thread lock. + // Non_Servant_Upcall has a magic constructor and destructor. We + // unlock the Object_Adapter lock for the duration of the servant + // activator upcalls; reacquiring once the upcalls complete. Even + // though we are releasing the lock, other threads will not be + // able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + +#if (TAO_HAS_MINIMUM_POA == 0) + this->adapter_activator_ = PortableServer::AdapterActivator::_nil (); + + this->servant_activator_ = PortableServer::ServantActivator::_nil (); + + this->servant_locator_ = PortableServer::ServantLocator::_nil (); + + this->default_servant_ = 0; +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + } + + CORBA::release (this); +} + +PortableServer::POA_ptr +TAO_POA::create_POA_i (const char *adapter_name, + PortableServer::POAManager_ptr poa_manager, + const CORBA::PolicyList &policies, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::AdapterAlreadyExists, + PortableServer::POA::InvalidPolicy)) +{ + // If any of the policy objects specified are not valid for the ORB + // implementation, if conflicting policy objects are specified, or + // if any of the specified policy objects require prior + // administrative action that has not been performed, an + // InvalidPolicy exception is raised containing the index in the + // policies parameter value of the first offending policy object. + TAO_POA_Policies tao_policies (this->orb_core_, + ACE_TRY_ENV); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + tao_policies.parse_policies (policies, + ACE_TRY_ENV); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // If the poa_manager parameter is null, a new POAManager object is + // created and associated with the new POA. Otherwise, the specified + // POAManager object is associated with the new POA. The POAManager + // object can be obtained using the attribute name the_POAManager. + + TAO_POA_Manager *tao_poa_manager = 0; + if (CORBA::is_nil (poa_manager)) + { + ACE_NEW_THROW_EX (tao_poa_manager, + TAO_POA_Manager (this->object_adapter ()), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + } + else + { + tao_poa_manager = ACE_dynamic_cast (TAO_POA_Manager *, + poa_manager); + } + + TAO_POA *poa = this->create_POA_i (adapter_name, + *tao_poa_manager, + tao_policies, + ACE_TRY_ENV); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + return PortableServer::POA::_duplicate (poa); +} + +TAO_POA * +TAO_POA::create_POA_i (const TAO_POA::String &adapter_name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policies &policies, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::AdapterAlreadyExists, + PortableServer::POA::InvalidPolicy)) +{ + // This operaton creates a new POA as a child of the target POA. The + // specified name identifies the new POA with respect to other POAs + // with the same parent POA. If the target POA already has a child + // POA with the specified name, the AdapterAlreadyExists exception + // is raised. + int result = this->children_.find (adapter_name); + + // Child was found + if (result != -1) + { + ACE_THROW_RETURN (PortableServer::POA::AdapterAlreadyExists (), + 0); + } + + // + // Child was not found + // + + // The specified policy objects are associated with the POA and used + // to control its behavior. The policy objects are effectively + // copied before this operation returns, so the application is free + // to destroy them while the POA is in use. Policies are not + // inherited from the parent POA. + TAO_POA *poa = 0; + ACE_NEW_THROW_EX (poa, + TAO_POA (adapter_name, + poa_manager, + policies, + this, + this->object_adapter ().lock (), + this->object_adapter ().thread_lock (), + this->orb_core_, + this->object_adapter_, + ACE_TRY_ENV), + CORBA::NO_MEMORY ()); + + // Give ownership of the new map to the auto pointer. Note, that it + // is important for the auto pointer to take ownership before + // checking for exception since we may need to delete the new map. + auto_ptr<TAO_POA> new_poa (poa); + + // Check for exception in construction of the POA. + ACE_CHECK_RETURN (0); + + // Add to children map + result = this->children_.bind (adapter_name, + new_poa.get ()); + if (result != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // Note: Creating a POA using a POA manager that is in the active + // state can lead to race conditions if the POA supports preexisting + // objects, because the new POA may receive a request before its + // adapter activator, servant manager, or default servant have been + // initialized. These problems do not occur if the POA is created by + // an adapter activator registered with a parent of the new POA, + // because requests are queued until the adapter activator + // returns. To avoid these problems when a POA must be explicitly + // initialized, the application can initialize the POA by invoking + // find_POA with a TRUE activate parameter. + + // Everything is fine. Don't let the auto_ptr delete the + // implementation. + return new_poa.release (); +} + +PortableServer::POA_ptr +TAO_POA::find_POA (const char *adapter_name, + CORBA::Boolean activate_it, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::AdapterNonExistent)) +{ + // Lock access for the duration of this transaction. + TAO_POA_GUARD_RETURN (0); + + // A recursive thread lock without using a recursive thread lock. + // Non_Servant_Upcall has a magic constructor and destructor. We + // unlock the Object_Adapter lock for the duration of the servant + // activator upcalls; reacquiring once the upcalls complete. Even + // though we are releasing the lock, other threads will not be able + // to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + TAO_POA *poa = this->find_POA_i (adapter_name, + activate_it, + ACE_TRY_ENV); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + return PortableServer::POA::_duplicate (poa); +} + +TAO_POA * +TAO_POA::find_POA_i (const ACE_CString &child_name, + CORBA::Boolean activate_it, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::AdapterNonExistent)) +{ + TAO_POA *child; + int result = this->children_.find (child_name, + child); + +#if (TAO_HAS_MINIMUM_POA == 0) + + if (result != 0) + { + if (activate_it) + { + if (!CORBA::is_nil (this->adapter_activator_.in ())) + { + // Check the state of the POA Manager. + this->check_poa_manager_state (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + CORBA::Boolean success = + this->adapter_activator_->unknown_adapter (this, + child_name.c_str (), + ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + if (success) + { + result = this->children_.find (child_name, + child); + } + else + { + result = -1; + } + } + else + { + result = -1; + } + } + else + { + result = -1; + } + } +#else + ACE_UNUSED_ARG (activate_it); +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + if (result == 0) + { + return child; + } + else + { + // Otherwise, the AdapterNonExistent exception is raised. + ACE_THROW_RETURN (PortableServer::POA::AdapterNonExistent (), + 0); + } +} + +void +TAO_POA::destroy_i (CORBA::Boolean etherealize_objects, + CORBA::Boolean wait_for_completion, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (this->cleanup_in_progress_) + return; + + // Is the <wait_for_completion> semantics for this thread correct? + TAO_POA::check_for_valid_wait_for_completions (wait_for_completion, + ACE_TRY_ENV); + ACE_CHECK; + + this->cleanup_in_progress_ = 1; + + // This operation destroys the POA and all descendant POAs. The POA + // so destroyed (that is, the POA with its name) may be re-created + // later in the same process. (This differs from the + // POAManager::deactivate operation that does not allow a + // re-creation of its associated POA in the same process.) + + // Remove POA from the parent + if (this->parent_ != 0) + { + int result = this->parent_->delete_child (this->name_); + if (result != 0) + { + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } + } + + // Remove all children POAs + for (CHILDREN::iterator iterator = this->children_.begin (); + iterator != this->children_.end (); + ++iterator) + { + TAO_POA *child_poa = (*iterator).int_id_; + child_poa->destroy_i (etherealize_objects, + wait_for_completion, + ACE_TRY_ENV); + ACE_CHECK; + } + + + // + // ImplRepo related. + // +#if (TAO_HAS_MINIMUM_CORBA == 0) + if (this->policies_.lifespan () == PortableServer::PERSISTENT) + { + this->imr_notify_shutdown (); + // Delete the servant, if there is one. + + if (this->server_object_) + { + TAO_POA *root_poa = this->object_adapter ().root_poa (); + + PortableServer::ObjectId_var id = + root_poa->servant_to_id_i (this->server_object_, ACE_TRY_ENV); + ACE_CHECK; + + root_poa->deactivate_object_i (id.in (), ACE_TRY_ENV); + ACE_CHECK; + + this->server_object_->_remove_ref (); + } + } +#endif /* TAO_HAS_MINIMUM_CORBA */ + + // When a POA is destroyed, any requests that have started execution + // continue to completion. Any requests that have not started + // execution are processed as if they were newly arrived, that is, + // the POA will attempt to cause recreation of the POA by invoking + // one or more adapter activators as described in Section 3.3.3. + + // If the wait_for_completion parameter is TRUE, the destroy + // operation will return only after all requests in process have + // completed and all invocations of etherealize have + // completed. Otherwise, the destroy operation returns after + // destroying the POAs. + + this->deactivate_all_objects_i (etherealize_objects, + wait_for_completion, + ACE_TRY_ENV); + ACE_CHECK; + + // If there are no outstanding requests. + if (this->outstanding_requests_ == 0) + { + this->complete_destruction_i (ACE_TRY_ENV); + ACE_CHECK; + } + else + { + // Mark that we are ready for destruction. + this->waiting_destruction_ = 1; + } +} + +int +TAO_POA::delete_child (const TAO_POA::String &child) +{ + int result = 0; + + // If we are not closing down, we must remove this child from our + // collection. + if (!this->cleanup_in_progress_) + result = this->children_.unbind (child); + + // Otherwise, if we are closing down, we are currently iterating + // over our children and there is not need to remove this child from + // our collection. + + return result; +} + +PortableServer::POAList * +TAO_POA::the_children_i (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + PortableServer::POAList_var children; + + ACE_NEW_THROW_EX (children, + PortableServer::POAList (this->children_.current_size ()), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (0); + + children->length (this->children_.current_size ()); + + CORBA::ULong index = 0; + for (CHILDREN::iterator iterator = this->children_.begin (); + iterator != this->children_.end (); + ++iterator, ++index) + { + TAO_POA *child_poa = (*iterator).int_id_; + children[index] = PortableServer::POA::_duplicate (child_poa); + } + + return children._retn (); +} + +#if (TAO_HAS_MINIMUM_POA == 0) + +PortableServer::ServantManager_ptr +TAO_POA::get_servant_manager_i (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the USE_SERVANT_MANAGER policy; if not + // present, the WrongPolicy exception is raised. + if (this->policies ().request_processing () != PortableServer::USE_SERVANT_MANAGER) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + PortableServer::ServantManager::_nil ()); + } + + // This operation returns the servant manager associated with the + // POA. If no servant manager has been associated with the POA, it + // returns a null reference. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + return PortableServer::ServantManager::_duplicate (this->servant_activator_.in ()); + else + return PortableServer::ServantManager::_duplicate (this->servant_locator_.in ()); +} + +void +TAO_POA::set_servant_manager_i (PortableServer::ServantManager_ptr imgr, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the USE_SERVANT_MANAGER policy; if not + // present, the WrongPolicy exception is raised. + if (this->policies ().request_processing () != PortableServer::USE_SERVANT_MANAGER) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + + // This operation sets the default servant manager associated with + // the POA. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + this->servant_activator_ = PortableServer::ServantActivator::_narrow (imgr, + ACE_TRY_ENV); + ACE_CHECK; + + if (CORBA::is_nil (this->servant_activator_.in ())) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + } + else + { + this->servant_locator_ = PortableServer::ServantLocator::_narrow (imgr, + ACE_TRY_ENV); + ACE_CHECK; + + if (CORBA::is_nil (this->servant_locator_.in ())) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + } +} + +PortableServer::Servant +TAO_POA::get_servant_i (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::NoServant, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the USE_DEFAULT_SERVANT policy; if not + // present, the WrongPolicy exception is raised. + if (this->policies ().request_processing () != PortableServer::USE_DEFAULT_SERVANT) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + 0); + } + + // This operation returns the default servant associated with the + // POA. + PortableServer::Servant result = this->default_servant_.in (); + if (result != 0) + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring once + // the upcalls complete. Even though we are releasing the lock, + // other threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been + // set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // The POA invokes _add_ref once on the Servant before returning + // it. If the application uses reference counting, the caller of + // get_servant is responsible for invoking _remove_ref once on + // the returned Servant when it is finished with it. A + // conforming caller need not invoke _remove_ref on the returned + // Servant if the type of the Servant uses the default reference + // counting inherited from ServantBase. + result->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + return result; + } + else + // If no servant has been associated with the POA, the NoServant + // exception is raised. + { + ACE_THROW_RETURN (PortableServer::POA::NoServant (), + 0); + } +} + +void +TAO_POA::set_servant_i (PortableServer::Servant servant, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the USE_DEFAULT_SERVANT policy; if not + // present, the WrongPolicy exception is raised. + if (this->policies ().request_processing () != PortableServer::USE_DEFAULT_SERVANT) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + + // This operation registers the specified servant with the POA as + // the default servant. This servant will be used for all requests + // for which no servant is found in the Active Object Map. + this->default_servant_ = servant; + + // The implementation of set_servant will invoke _add_ref at least + // once on the Servant argument before returning. When the POA no + // longer needs the Servant, it will invoke _remove_ref on it the + // same number of times. + if (servant != 0) + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring once + // the upcalls complete. Even though we are releasing the lock, + // other threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been + // set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK; + + // If we are a single threaded POA, set up the appropriate + // locking in the servant. + this->establish_servant_lock (servant); + } +} + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + +int +TAO_POA::is_servant_in_map (PortableServer::Servant servant) +{ + while (1) + { + int deactivated = 0; + int servant_in_map = + this->active_object_map ().is_servant_in_map (servant, + deactivated); + + if (!servant_in_map) + { + return 0; + } + else + { + if (deactivated) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) TAO_POA::is_servant_in_map: waiting for servant to deactivate\n"))); + + ++this->waiting_servant_deactivation_; + + if (this->object_adapter ().enable_locking_) + this->servant_deactivation_condition_.wait (); + + --this->waiting_servant_deactivation_; + } + else + { + return 1; + } + } + } +} + +int +TAO_POA::is_user_id_in_map (const PortableServer::ObjectId &id, + CORBA::Short priority, + int &priorities_match) +{ + while (1) + { + int deactivated = 0; + int user_id_in_map = + this->active_object_map ().is_user_id_in_map (id, + priority, + priorities_match, + deactivated); + + if (!user_id_in_map) + { + return 0; + } + else + { + if (deactivated) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) TAO_POA::is_user_id_in_map: waiting for servant to deactivate\n"))); + + ++this->waiting_servant_deactivation_; + + if (this->object_adapter ().enable_locking_) + this->servant_deactivation_condition_.wait (); + + --this->waiting_servant_deactivation_; + } + else + { + return 1; + } + } + } +} + +PortableServer::ObjectId * +TAO_POA::activate_object_i (PortableServer::Servant servant, + CORBA::Short priority, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ServantAlreadyActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the SYSTEM_ID and RETAIN policy; if not + // present, the WrongPolicy exception is raised. + if (!(this->policies ().id_assignment () == PortableServer::SYSTEM_ID && + this->policies ().servant_retention () == PortableServer::RETAIN)) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + 0); + } + + // If the POA has the UNIQUE_ID policy and the specified servant is + // already in the Active Object Map, the ServantAlreadyActive + // exception is raised. + if (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID && + this->is_servant_in_map (servant)) + { + ACE_THROW_RETURN (PortableServer::POA::ServantAlreadyActive (), + 0); + } + + // Otherwise, the activate_object operation generates an Object Id + // and enters the Object Id and the specified servant in the Active + // Object Map. The Object Id is returned. + PortableServer::ObjectId_var user_id; + if (this->active_object_map ().bind_using_system_id_returning_user_id (servant, + priority, + user_id.out ()) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // + // Everything is finally ok + // + + // A recursive thread lock without using a recursive thread lock. + // Non_Servant_Upcall has a magic constructor and destructor. We + // unlock the Object_Adapter lock for the duration of the servant + // activator upcalls; reacquiring once the upcalls complete. Even + // though we are releasing the lock, other threads will not be able + // to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // The implementation of activate_object will invoke _add_ref at + // least once on the Servant argument before returning. When the POA + // no longer needs the Servant, it will invoke _remove_ref on it the + // same number of times. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + // If we are a single threaded POA, set up the appropriate locking + // in the servant. + this->establish_servant_lock (servant); + + return user_id._retn (); +} + +void +TAO_POA::activate_object_with_id_i (const PortableServer::ObjectId &id, + PortableServer::Servant servant, + CORBA::Short priority, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ServantAlreadyActive, + PortableServer::POA::ObjectAlreadyActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN policy; if not present, the + // WrongPolicy exception is raised. + if (this->policies ().servant_retention () != PortableServer::RETAIN) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + + // If the POA has the SYSTEM_ID policy and it detects that the + // Object Id value was not generated by the system or for this POA, + // the activate_object_with_id operation may raise the BAD_PARAM + // system exception. An ORB is not required to detect all such + // invalid Object Id values, but a portable application must not + // invoke activate_object_with_id on a POA that has the SYSTEM_ID + // policy with an Object Id value that was not previously generated + // by the system for that POA, or, if the POA also has the + // PERSISTENT policy, for a previous instantiation of the same POA. + if (this->policies ().id_assignment () == PortableServer::SYSTEM_ID && + !this->is_poa_generated_id (id)) + { + ACE_THROW (CORBA::BAD_PARAM ()); + } + + // If the CORBA object denoted by the Object Id value is already + // active in this POA (there is a servant bound to it in the Active + // Object Map), the ObjectAlreadyActive exception is raised. + int priorities_match = 1; + if (is_user_id_in_map (id, + priority, + priorities_match)) + { + ACE_THROW (PortableServer::POA::ObjectAlreadyActive ()); + } + + // If the activate_object_with_id_and_priority operation is invoked + // with a different priority to an earlier invocation of one of the + // create reference with priority operations, for the same object, + // then the ORB shall raise a BAD_INV_ORDER system exception (with a + // Standard Minor Exception Code of 1). If the priority value is the + // same then the ORB shall return SUCCESS. + if (!priorities_match) + { + ACE_THROW (CORBA::BAD_INV_ORDER (1, + CORBA::COMPLETED_NO)); + } + + // If the POA has the UNIQUE_ID policy and the servant is already in + // the Active Object Map, the ServantAlreadyActive exception is + // raised. + if (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID && + this->is_servant_in_map (servant)) + { + ACE_THROW (PortableServer::POA::ServantAlreadyActive ()); + } + + // Otherwise, the activate_object_with_id operation enters an + // association between the specified Object Id and the specified + // servant in the Active Object Map. + if (this->active_object_map ().bind_using_user_id (servant, + id, + priority) != 0) + { + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } + + // + // Everything is finally ok + // + + // A recursive thread lock without using a recursive thread lock. + // Non_Servant_Upcall has a magic constructor and destructor. We + // unlock the Object_Adapter lock for the duration of the servant + // activator upcalls; reacquiring once the upcalls complete. Even + // though we are releasing the lock, other threads will not be able + // to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // The implementation of activate_object_with_id will invoke + // _add_ref at least once on the Servant argument before + // returning. When the POA no longer needs the Servant, it will + // invoke _remove_ref on it the same number of times. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK; + + // If we are a single threaded POA, set up the appropriate locking + // in the servant. + this->establish_servant_lock (servant); +} + +void +TAO_POA::deactivate_all_objects_i (CORBA::Boolean etherealize_objects, + CORBA::Boolean wait_for_completion, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + this->deactivate_all_objects_i (etherealize_objects, + ACE_TRY_ENV); + ACE_CHECK; + + this->wait_for_completions (wait_for_completion, + ACE_TRY_ENV); + ACE_CHECK; +} + +void +TAO_POA::wait_for_completions (CORBA::Boolean wait_for_completion, + CORBA::Environment &ACE_TRY_ENV) +{ + while (this->object_adapter ().enable_locking_ && + wait_for_completion && + this->outstanding_requests_ > 0) + { + this->wait_for_completion_pending_ = 1; + + int result = this->outstanding_requests_condition_.wait (); + if (result == -1) + { + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } + } +} + +/* static */ +void +TAO_POA::check_for_valid_wait_for_completions (CORBA::Boolean wait_for_completion, + CORBA::Environment &ACE_TRY_ENV) +{ + if (wait_for_completion) + { + TAO_POA_Current_Impl *poa_current_impl = + ACE_static_cast(TAO_POA_Current_Impl *, + TAO_TSS_RESOURCES::instance ()->poa_current_impl_); + + // This thread cannot currently be in an upcall. + if (poa_current_impl != 0) + { + // CORBA 2.3 specifies which minor code corresponds to this + // particular problem. + ACE_THROW (CORBA::BAD_INV_ORDER (3, CORBA::COMPLETED_NO)); + } + } +} + +void +TAO_POA::deactivate_all_objects_i (CORBA::Boolean etherealize_objects, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + this->etherealize_objects_ = etherealize_objects; + + // This operation is a no-op for the non-RETAIN policy. + if (this->policies ().servant_retention () != PortableServer::RETAIN) + { + return; + } + + // If the etherealize_objects parameter is TRUE, the POA has the + // RETAIN policy, and a servant manager is registered with the POA, + // the etherealize operation on the servant manager will be called + // for each active object in the Active Object Map. The apparent + // destruction of the POA occurs before any calls to etherealize are + // made. Thus, for example, an etherealize method that attempts to + // invoke operations on the POA will receive the OBJECT_NOT_EXIST + // exception. + + // We must copy the user ids into a separate place since we cannot + // remove entries while iterating through the map. + ACE_Array<PortableServer::ObjectId> ids (this->active_object_map ().current_size ()); + + size_t counter = 0; + TAO_Active_Object_Map::user_id_map::iterator end + = this->active_object_map ().user_id_map_->end (); + + for (TAO_Active_Object_Map::user_id_map::iterator iter + = this->active_object_map ().user_id_map_->begin (); + iter != end; + ++iter) + { + TAO_Active_Object_Map::user_id_map::value_type map_pair = *iter; + TAO_Active_Object_Map::Map_Entry *active_object_map_entry = map_pair.second (); + + if (!active_object_map_entry->deactivated_) + { + ids[counter] = active_object_map_entry->user_id_; + ++counter; + } + } + + for (size_t i = 0; + i < counter; + ++i) + { + this->deactivate_object_i (ids[i], + ACE_TRY_ENV); + ACE_CHECK; + } +} + +void +TAO_POA::deactivate_object_i (const PortableServer::ObjectId &id, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ObjectNotActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN policy; if not present, the + // WrongPolicy exception is raised. + if (this->policies ().servant_retention () != PortableServer::RETAIN) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + + TAO_Active_Object_Map::Map_Entry *active_object_map_entry = 0; + int result = this->active_object_map ().find_servant_and_system_id_using_user_id (id, + active_object_map_entry); + + // If there is no active object associated with the specified Object + // Id, the operation raises an ObjectNotActive exception. + if (result != 0) + { + ACE_THROW (PortableServer::POA::ObjectNotActive ()); + } + + // Decrement the reference count. + CORBA::UShort new_count = --active_object_map_entry->reference_count_; + + if (new_count == 0) + { + this->cleanup_servant (active_object_map_entry, + ACE_TRY_ENV); + ACE_CHECK; + } + else + { + // It should be noted that there may be a period of time between + // an object's deactivation and the etherealization (during + // which outstanding requests are being processed) in which + // arriving requests on that object should not be passed to its + // servant. During this period, requests targeted for such an + // object act as if the POA were in holding state until + // etherealize completes. If etherealize is called as a + // consequence of a deactivate call with a etherealize_objects + // parameter of TRUE, incoming requests are rejected. + + // Else mark entry as closed... + active_object_map_entry->deactivated_ = 1; + } +} + +void +TAO_POA::cleanup_servant (TAO_Active_Object_Map::Map_Entry *active_object_map_entry, + CORBA::Environment &ACE_TRY_ENV) +{ + // If a servant manager is associated with the POA, + // ServantLocator::etherealize will be invoked with the oid and the + // servant. (The deactivate_object operation does not wait for the + // etherealize operation to complete before deactivate_object + // returns.) + // + // Note: If the servant associated with the oid is serving multiple + // Object Ids, ServantLocator::etherealize may be invoked multiple + // times with the same servant when the other objects are + // deactivated. It is the responsibility of the object + // implementation to refrain from destroying the servant while it is + // active with any Id. + + // If the POA has no ServantActivator associated with it, the POA + // implementation calls _remove_ref when all operation invocations + // have completed. If there is a ServantActivator, the Servant is + // consumed by the call to ServantActivator::etherealize instead. + + // First check for a non-zero servant. + if (active_object_map_entry->servant_) + { + // If we are a single threaded POA, teardown the appropriate + // locking in the servant. + // + // Note that teardown of the servant lock must happen before the + // _remove_ref() or etherealize() calls since they might end up + // deleting the servant. + // + this->teardown_servant_lock (active_object_map_entry->servant_); + +#if (TAO_HAS_MINIMUM_POA == 0) + + if (this->etherealize_objects_ && + this->policies ().request_processing () == PortableServer::USE_SERVANT_MANAGER && + !CORBA::is_nil (this->servant_activator_.in ())) + { + CORBA::Boolean remaining_activations = + this->active_object_map ().remaining_activations (active_object_map_entry->servant_); + + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring + // once the upcalls complete. Even though we are releasing + // the lock, other threads will not be able to make progress + // since <Object_Adapter::non_servant_upcall_in_progress_> + // has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // If the cleanup_in_progress parameter is TRUE, the reason + // for the etherealize operation is that either the + // deactivate or destroy operation was called with an + // etherealize_objects parameter of TRUE. If the parameter + // is FALSE, the etherealize operation is called for other + // reasons. + this->servant_activator_->etherealize (active_object_map_entry->user_id_, + this, + active_object_map_entry->servant_, + this->cleanup_in_progress_, + remaining_activations + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + } + else + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring + // once the upcalls complete. Even though we are releasing + // the lock, other threads will not be able to make progress + // since <Object_Adapter::non_servant_upcall_in_progress_> + // has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + active_object_map_entry->servant_->_remove_ref (ACE_TRY_ENV); + ACE_CHECK; + } + } + + // This operation causes the association of the Object Id specified + // by the oid parameter and its servant to be removed from the + // Active Object Map. + int result = this->active_object_map ().unbind_using_user_id (active_object_map_entry->user_id_); + + if (result != 0) + { + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } +} + +void +TAO_POA::check_poa_manager_state (CORBA::Environment &ACE_TRY_ENV) +{ + PortableServer::POAManager::State state = this->poa_manager_.get_state_i (); + + if (state == PortableServer::POAManager::ACTIVE) + { + // When a POA manager is in the active state, the associated + // POAs will receive and start processing requests (assuming + // that appropriate thread resources are available). + return; + } + + if (state == PortableServer::POAManager::DISCARDING) + { + // When a POA manager is in the discarding state, the associated + // POAs will discard all incoming requests (whose processing has + // not yet begun). When a request is discarded, the TRANSIENT + // system exception must be returned to the client-side to + // indicate that the request should be re-issued. (Of course, an + // ORB may always reject a request for other reasons and raise + // some other system exception.) + ACE_THROW ( + CORBA::TRANSIENT ( + CORBA_SystemException::_tao_minor_code ( + TAO_POA_DISCARDING, + 0), + CORBA::COMPLETED_NO)); + } + + if (state == PortableServer::POAManager::HOLDING) + { + // When a POA manager is in the holding state, the associated + // POAs will queue incoming requests. The number of requests + // that can be queued is an implementation limit. If this limit + // is reached, the POAs may discard requests and return the + // TRANSIENT system exception to the client to indicate that the + // client should reissue the request. (Of course, an ORB may + // always reject a request for other reasons and raise some + // other system exception.) + + // Since there is no queuing in TAO, we immediately raise a + // TRANSIENT exception. + ACE_THROW (CORBA::TRANSIENT ( + CORBA_SystemException::_tao_minor_code ( + TAO_POA_HOLDING, + 0), + CORBA::COMPLETED_NO)); + } + + if (state == PortableServer::POAManager::INACTIVE) + { + // The inactive state is entered when the associated POAs are to + // be shut down. Unlike the discarding state, the inactive state + // is not a temporary state. When a POA manager is in the + // inactive state, the associated POAs will reject new + // requests. The rejection mechanism used is specific to the + // vendor. The GIOP location forwarding mechanism and + // CloseConnection message are examples of mechanisms that could + // be used to indicate the rejection. If the client is + // co-resident in the same process, the ORB could raise the + // OBJ_ADAPTER exception to indicate that the object + // implementation is unavailable. + ACE_THROW (CORBA::OBJ_ADAPTER ()); + } +} + +CORBA::Object_ptr +TAO_POA::create_reference_i (const char *intf, + CORBA::Short priority, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the SYSTEM_ID policy; if not present, the + // WrongPolicy exception is raised. + if (this->policies ().id_assignment () != PortableServer::SYSTEM_ID) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + CORBA::Object::_nil ()); + } + + // This operation creates an object reference that encapsulates a + // POA-generated Object Id value and the specified interface + // repository id. This operation does not cause an activation to + // take place. The resulting reference may be passed to clients, so + // that subsequent requests on those references will cause the + // appropriate servant manager to be invoked, if one is + // available. The generated Object Id value may be obtained by + // invoking POA::reference_to_id with the created reference. + + PortableServer::ObjectId_var system_id; + + // Do the following if we going to retain this object in the active + // object map. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + if (this->active_object_map ().bind_using_system_id_returning_system_id (0, + priority, + system_id.out ()) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + CORBA::Object::_nil ()); + } + } + else + { + // Otherwise, it is the NON_RETAIN policy. Therefore, any ol' + // object id will do (even an empty one). + PortableServer::ObjectId *sys_id; + ACE_NEW_THROW_EX (sys_id, + PortableServer::ObjectId, + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + system_id = sys_id; + } + + // Create object key. + TAO_ObjectKey_var key = this->create_object_key (system_id.in ()); + + // Ask the ORB to create you a reference + return this->key_to_object (key.in (), + intf, + 0, + 1, + priority, + ACE_TRY_ENV); +} + +CORBA::Object_ptr +TAO_POA::create_reference_with_id_i (const PortableServer::ObjectId &user_id, + const char *intf, + CORBA::Short priority, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongPolicy)) +{ + // If the POA has the SYSTEM_ID policy and it detects that the + // Object Id value was not generated by the system or for this POA, + // the create_reference_with_id operation may raise the BAD_PARAM + // system exception. An ORB is not required to detect all such + // invalid Object Id values, but a portable application must not + // invoke this operation on a POA that has the SYSTEM_ID policy with + // an Object Id value that was not previously generated by the + // system for that POA, or, if the POA also has the PERSISTENT + // policy, for a previous instantiation of the same POA. + if (this->policies ().id_assignment () == PortableServer::SYSTEM_ID && + !this->is_poa_generated_id (user_id)) + { + ACE_THROW_RETURN (CORBA::BAD_PARAM (), + CORBA::Object::_nil ()); + } + + // This operation creates an object reference that encapsulates the + // specified Object Id and interface repository Id values. This + // operation does not cause an activation to take place. The + // resulting reference may be passed to clients, so that subsequent + // requests on those references will cause the object to be + // activated if necessary, or the default servant used, depending on + // the applicable policies. + + PortableServer::Servant servant = 0; + PortableServer::ObjectId_var system_id; + + // Do the following if we going to retain this object in the active + // object map. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + // @@ We need something that can find the system id using + // appropriate strategy, at the same time, return the servant if + // one is available. Before we have that function, + // <create_reference_with_id_i> basically generates broken + // collocated object when DIRECT collocation strategy is used. + + if (this->active_object_map ().find_system_id_using_user_id (user_id, + priority, + system_id.out ()) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + CORBA::Object::_nil ()); + } + } + else + { + // Otherwise, it is the NON_RETAIN policy. Therefore, user id + // is the same as system id. + PortableServer::ObjectId *sys_id; + ACE_NEW_THROW_EX (sys_id, + PortableServer::ObjectId (user_id), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + system_id = sys_id; + } + + // Create object key. + TAO_ObjectKey_var key = this->create_object_key (system_id.in ()); + + // Ask the ORB to create you a reference + return this->key_to_object (key.in (), + intf, + servant, + 1, + priority, + ACE_TRY_ENV); +} + +PortableServer::ObjectId * +TAO_POA::servant_to_id_i (PortableServer::Servant servant, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ServantNotActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN and either the UNIQUE_ID or + // IMPLICIT_ACTIVATION policies; or it requires the USE_DEFAULT_SERVANT + // policy; if not present, the WrongPolicy exception is raised. + if (!(this->policies ().servant_retention () == PortableServer::RETAIN + && (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID + || this->policies ().implicit_activation () == PortableServer::IMPLICIT_ACTIVATION)) + && !(this->policies ().request_processing () == PortableServer::USE_DEFAULT_SERVANT)) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + 0); + } + + // This operation has four possible behaviors. + + // If the POA has the UNIQUE_ID policy and the specified servant is + // active, the Object Id associated with that servant is returned. + PortableServer::ObjectId_var user_id; + if (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID && + this->active_object_map ().find_user_id_using_servant (servant, + user_id.out ()) != -1) + { + return user_id._retn (); + } + + // If the POA has the IMPLICIT_ACTIVATION policy and either the POA + // has the MULTIPLE_ID policy or the specified servant is not + // active, the servant is activated using a POA-generated Object Id + // and the Interface Id associated with the servant, and that Object + // Id is returned. + if (this->policies ().implicit_activation () == PortableServer::IMPLICIT_ACTIVATION) + { + // If we reach here, then we either have the MULTIPLE_ID policy + // or we have the UNIQUE_ID policy and we are not in the active + // object map. + PortableServer::ObjectId_var user_id; + if (this->active_object_map ().bind_using_system_id_returning_user_id (servant, + TAO_INVALID_PRIORITY, + user_id.out ()) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // + // Everything is finally ok + // + + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring once + // the upcalls complete. Even though we are releasing the lock, + // other threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been + // set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // If this operation causes the object to be activated, _add_ref + // is invoked at least once on the Servant argument before + // returning. Otherwise, the POA does not increment or decrement + // the reference count of the Servant passed to this function. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + // If we are a single threaded POA, set up the appropriate + // locking in the servant. + this->establish_servant_lock (servant); + + return user_id._retn (); + } + +#if (TAO_HAS_MINIMUM_POA == 0) + + // If the POA has the USE_DEFAULT_SERVANT policy, the servant + // specified is the default servant, and the operation is being + // invoked in he context of executin a request on the default + // servant, then the ObjectId associated with the current invocation + // is returned. + if (this->policies ().request_processing () == PortableServer::USE_DEFAULT_SERVANT) + { + // Compare the servant specified in the parameter list to the + // default servant registered with this POA. + PortableServer::Servant default_servant = this->default_servant_.in (); + if (default_servant != 0 && + default_servant == servant) + { + // If they are the same servant, then check if we are in an + // upcall. + TAO_POA_Current_Impl *poa_current_impl = + ACE_static_cast(TAO_POA_Current_Impl *, + TAO_TSS_RESOURCES::instance ()->poa_current_impl_); + // If we are in an upcall on the default servant, return the + // ObjectId associated with the current invocation. + if (poa_current_impl != 0 && + servant == poa_current_impl->servant ()) + { + return poa_current_impl->get_object_id (ACE_TRY_ENV); + } + } + } + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + // Otherwise, the ServantNotActive exception is raised. + ACE_THROW_RETURN (PortableServer::POA::ServantNotActive (), + 0); +} + +PortableServer::ObjectId * +TAO_POA::servant_to_system_id_i (PortableServer::Servant servant, + CORBA::Short &priority, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ServantNotActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN and either the UNIQUE_ID or + // IMPLICIT_ACTIVATION policies; if not present, the WrongPolicy + // exception is raised. + if (!(this->policies ().servant_retention () == PortableServer::RETAIN + && (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID + || this->policies ().implicit_activation () == PortableServer::IMPLICIT_ACTIVATION))) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + 0); + } + + // This operation has three possible behaviors. + + // If the POA has the UNIQUE_ID policy and the specified servant is + // active, the Object Id associated with that servant is returned. + PortableServer::ObjectId_var system_id; + if (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID && + this->active_object_map ().find_system_id_using_servant (servant, + system_id.out (), + priority) != -1) + { + return system_id._retn (); + } + + // If the POA has the IMPLICIT_ACTIVATION policy and either the POA + // has the MULTIPLE_ID policy or the specified servant is not + // active, the servant is activated using a POA-generated Object Id + // and the Interface Id associated with the servant, and that Object + // Id is returned. + if (this->policies ().implicit_activation () == PortableServer::IMPLICIT_ACTIVATION) + { + // If we reach here, then we either have the MULTIPLE_ID policy + // or we xhave the UNIQUE_ID policy and we are not in the active + // object map. + PortableServer::ObjectId_var system_id; + if (this->active_object_map ().bind_using_system_id_returning_system_id (servant, + priority, + system_id.out ()) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // + // Everything is finally ok + // + + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring once + // the upcalls complete. Even though we are releasing the lock, + // other threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been + // set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // If this operation causes the object to be activated, _add_ref + // is invoked at least once on the Servant argument before + // returning. Otherwise, the POA does not increment or decrement + // the reference count of the Servant passed to this function. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + // If we are a single threaded POA, set up the appropriate + // locking in the servant. + this->establish_servant_lock (servant); + + return system_id._retn (); + } + + // Otherwise, the ServantNotActive exception is raised. + ACE_THROW_RETURN (PortableServer::POA::ServantNotActive (), + 0); +} + +CORBA::Object_ptr +TAO_POA::servant_to_reference (PortableServer::Servant servant, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ServantNotActive, + PortableServer::POA::WrongPolicy)) +{ + // Note: The allocation of an Object Id value and installation in + // the Active Object Map caused by implicit activation may actually + // be deferred until an attempt is made to externalize the + // reference. The real requirement here is that a reference is + // produced that will behave appropriately (that is, yield a + // consistent Object Id value when asked politely). + CORBA::Short priority = TAO_INVALID_PRIORITY; + PortableServer::ObjectId_var id = this->servant_to_system_id (servant, + priority, + ACE_TRY_ENV); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + // Create object key. + TAO_ObjectKey_var key = this->create_object_key (id.in ()); + + // Ask the ORB to create you a reference + return this->key_to_object (key.in (), + servant->_interface_repository_id (), + servant, + 1, + priority, + ACE_TRY_ENV); +} + +PortableServer::Servant +TAO_POA::reference_to_servant (CORBA::Object_ptr reference, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ObjectNotActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN policy or the + // USE_DEFAULT_SERVANT policy. If neither policy is present, the + // WrongPolicy exception is raised. + if (!(this->policies ().servant_retention () == PortableServer::RETAIN + || this->policies ().request_processing () == PortableServer::USE_DEFAULT_SERVANT)) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + 0); + } + + // If the POA has the RETAIN policy and the specified object is + // present in the Active Object Map, this operation returns the + // servant associated with that object in the Active Object Map. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + TAO_ObjectKey_var key = reference->_key (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + // If the object reference was not created by this POA, the + // WrongAdapter exception is raised. + PortableServer::ObjectId system_id; + TAO_Object_Adapter::poa_name poa_system_name; + CORBA::Boolean is_root = 0; + CORBA::Boolean is_persistent = 0; + CORBA::Boolean is_system_id = 0; + TAO_Temporary_Creation_Time poa_creation_time; + + int result = this->parse_key (key.in (), + poa_system_name, + system_id, + is_root, + is_persistent, + is_system_id, + poa_creation_time); + if (result != 0 || + !this->root () && + poa_system_name != this->system_name () || + is_root != this->root () || + is_persistent != this->persistent () || + is_system_id != this->system_id () || + !this->persistent () && + poa_creation_time != this->creation_time_) + { + ACE_THROW_RETURN (PortableServer::POA::WrongAdapter (), + 0); + } + + // Lock access for the duration of this transaction. + TAO_POA_GUARD_RETURN (0); + + // Find user id from system id. + PortableServer::ObjectId user_id; + if (this->active_object_map ().find_user_id_using_system_id (system_id, + user_id) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // This operation returns the active servant associated with the + // specified system Object Id value. If the Object Id value is + // not active in the POA, an ObjectNotActive exception is + // raised. + PortableServer::Servant servant = 0; + TAO_Active_Object_Map::Map_Entry *entry = 0; + + if (this->active_object_map ().find_servant_using_system_id_and_user_id (system_id, + user_id, + servant, + entry) != -1) + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring + // once the upcalls complete. Even though we are releasing + // the lock, other threads will not be able to make progress + // since <Object_Adapter::non_servant_upcall_in_progress_> + // has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // The POA invokes _add_ref once on the Servant before + // returning it. If the application uses reference counting, + // the caller of reference_to_servant is responsible for + // invoking _remove_ref once on the returned Servant when it + // is finished with it. A conforming caller need not invoke + // _remove_ref on the returned Servant if the type of the + // Servant uses the default reference counting inherited + // from ServantBase. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + return servant; + } + else + // Otherwise, the ObjectNotActive exception is raised. + { + ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (), + 0); + } + } + +#if (TAO_HAS_MINIMUM_POA == 0) + + // Otherwise, if the POA has the USE_DEFAULT_SERVANT policy and a + // default servant has been registered with the POA, this operation + // returns the default servant. + if (this->policies ().request_processing () == PortableServer::USE_DEFAULT_SERVANT) + { + // Lock access for the duration of this transaction. + TAO_POA_GUARD_RETURN (0); + + PortableServer::Servant result = this->default_servant_.in (); + if (result != 0) + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring + // once the upcalls complete. Even though we are releasing + // the lock, other threads will not be able to make progress + // since <Object_Adapter::non_servant_upcall_in_progress_> + // has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // The POA invokes _add_ref once on the Servant before + // returning it. If the application uses reference counting, + // the caller of reference_to_servant is responsible for + // invoking _remove_ref once on the returned Servant when it + // is finished with it. A conforming caller need not invoke + // _remove_ref on the returned Servant if the type of the + // Servant uses the default reference counting inherited + // from ServantBase. + result->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + return result; + } + else + // Otherwise, the ObjectNotActive exception is raised. + { + ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (), + 0); + } + } + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + // Not reached + return 0; +} + +PortableServer::ObjectId * +TAO_POA::reference_to_id (CORBA::Object_ptr reference, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::WrongAdapter, + PortableServer::POA::WrongPolicy)) +{ + // The WrongPolicy exception is declared to allow future extensions. + + // This operation returns the Object Id value encapsulated by the + // specified reference. + + // This operation is valid only if the reference was created by the + // POA on which the operation is being performed. If the object + // reference was not created by this POA, the WrongAdapter exception + // is raised. + TAO_ObjectKey_var key = reference->_key (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + PortableServer::ObjectId system_id; + TAO_Object_Adapter::poa_name poa_system_name; + CORBA::Boolean is_root = 0; + CORBA::Boolean is_persistent = 0; + CORBA::Boolean is_system_id = 0; + TAO_Temporary_Creation_Time poa_creation_time; + + int result = this->parse_key (key.in (), + poa_system_name, + system_id, + is_root, + is_persistent, + is_system_id, + poa_creation_time); + if (result != 0 || + !this->root () && + poa_system_name != this->system_name () || + is_root != this->root () || + is_persistent != this->persistent () || + is_system_id != this->system_id () || + !this->persistent () && + poa_creation_time != this->creation_time_) + { + ACE_THROW_RETURN (PortableServer::POA::WrongAdapter (), + 0); + } + + // Do the following if we have the RETAIN policy. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + // Lock access for the duration of this transaction. + TAO_POA_GUARD_RETURN (0); + + // The object denoted by the reference does not have to be + // active for this operation to succeed. + PortableServer::ObjectId_var user_id; + if (this->active_object_map ().find_user_id_using_system_id (system_id, + user_id.out ()) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + return user_id._retn (); + } + else + { + // Otherwise, it is the NON_RETAIN policy. Therefore, the + // system id is the id (and no conversion/transformation is + // needed). + return new PortableServer::ObjectId (system_id); + } +} + +PortableServer::Servant +TAO_POA::id_to_servant_i (const PortableServer::ObjectId &id, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ObjectNotActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN policy; if not present, the + // WrongPolicy exception is raised. + if (this->policies ().servant_retention () != PortableServer::RETAIN) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + 0); + } + + // This operation returns the active servant associated with the + // specified Object Id value. If the Object Id value is not active + // in the POA, an ObjectNotActive exception is raised. + PortableServer::Servant servant = 0; + if (this->active_object_map ().find_servant_using_user_id (id, + servant) != -1) + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring once + // the upcalls complete. Even though we are releasing the lock, + // other threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has been + // set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // The POA invokes _add_ref once on the Servant before returning + // it. If the application uses reference counting, the caller of + // id_to_servant is responsible for invoking _remove_ref once on + // the returned Servant when it is finished with it. A + // conforming caller need not invoke _remove_ref on the returned + // Servant if the type of the Servant uses the default reference + // counting inherited from ServantBase. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + return servant; + } + else + // Otherwise, the ObjectNotActive exception is raised. + { + ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (), + 0); + } +} + +CORBA::Object_ptr +TAO_POA::id_to_reference_i (const PortableServer::ObjectId &id, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + PortableServer::POA::ObjectNotActive, + PortableServer::POA::WrongPolicy)) +{ + // This operation requires the RETAIN policy; if not present, the + // WrongPolicy exception is raised. + if (this->policies ().servant_retention () != PortableServer::RETAIN) + { + ACE_THROW_RETURN (PortableServer::POA::WrongPolicy (), + CORBA::Object::_nil ()); + } + + // If an object with the specified Object Id value is currently + // active, a reference encapsulating the information used to + // activate the object is returned. + PortableServer::ObjectId_var system_id; + PortableServer::Servant servant; + CORBA::Short priority; + if (this->active_object_map ().find_servant_and_system_id_using_user_id (id, + servant, + system_id.out (), + priority) == 0) + { + // Create object key. + TAO_ObjectKey_var key = this->create_object_key (system_id.in ()); + + // Ask the ORB to create you a reference + return this->key_to_object (key.in (), + servant->_interface_repository_id (), + servant, + 1, + priority, + ACE_TRY_ENV); + } + else + // If the Object Id value is not active in the POA, an + // ObjectNotActive exception is raised. + { + ACE_THROW_RETURN (PortableServer::POA::ObjectNotActive (), + CORBA::Object::_nil ()); + } +} + +#if (TAO_HAS_RT_CORBA == 1) + +int +TAO_POA::valid_priority (RTCORBA::Priority /* priority */) +{ + return 1; +} + +void +TAO_POA::validate_priority_and_policies (RTCORBA::Priority priority, + CORBA::Environment &ACE_TRY_ENV) +{ + // For each of the above operations, if the POA supports the + // IMPLICIT_ACTIVATION option for the ImplicitActivationPolicy then + // the ORB shall raise a WrongPolicy user exception. This relieves + // an ORB implementation of the need to retrieve the target object's + // priority from "somewhere" when a request arrives for an inactive + // object. + if (this->policies ().implicit_activation () == PortableServer::IMPLICIT_ACTIVATION) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + + // For each of the above operations, if the POA does not support the + // SERVER_DECLARED option for the PriorityModelPolicy then the ORB + // shall raise a WrongPolicy user exception. + if (this->policies ().priority_model () != TAO_POA_Policies::SERVER_DECLARED) + { + ACE_THROW (PortableServer::POA::WrongPolicy ()); + } + + // If the priority parameter of any of the above operations is not a + // valid CORBA priority or if it fails to match the priority + // configuration for resources assigned to the POA, then the ORB + // shall raise a BAD_PARAM system exception. + if (!this->valid_priority (priority)) + { + ACE_THROW (PortableServer::POA::ObjectNotActive ()); + } + + // In all other respects the semantics of the corresponding + // (i.e. without the name extensions "_with_priority" and + // "_and_priority") PortableServer::POA operations shall be + // observed. +} + +#endif /* TAO_HAS_RT_CORBA */ + +// +// Forwarding related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) + +void +TAO_POA::forward_object_i (const PortableServer::ObjectId &oid, + CORBA::Object_ptr forward_to, + CORBA::Environment &ACE_TRY_ENV) +{ + // First, deactivate the object + this->deactivate_object_i (oid, + ACE_TRY_ENV); + ACE_CHECK; + + // Create a forwarding servant + TAO_Forwarding_Servant *forwarding_servant = 0; + ACE_NEW_THROW_EX (forwarding_servant, + TAO_Forwarding_Servant (forward_to, + forward_to->_interface_repository_id ()), + CORBA::NO_MEMORY ()); + ACE_CHECK; + + // Give ownership to the auto pointer. + auto_ptr<TAO_Forwarding_Servant> new_forwarding_servant (forwarding_servant); + + // Register the forwarding servant with the same object Id. + this->activate_object_with_id_i (oid, + forwarding_servant, + TAO_INVALID_PRIORITY, + ACE_TRY_ENV); + ACE_CHECK; + + // Finally everything is fine. Make sure to take ownership away + // from the auto pointer. + new_forwarding_servant.release (); +} + +#endif /* TAO_HAS_MINIMUM_CORBA */ + +TAO_SERVANT_LOCATION +TAO_POA::locate_servant_i (const PortableServer::ObjectId &system_id, + PortableServer::Servant &servant, + CORBA::Environment &ACE_TRY_ENV) +{ + // If the POA has the RETAIN policy, the POA looks in the Active + // Object Map to find if there is a servant associated with the + // Object Id value from the request. If such a servant exists, + // return TAO_SERVANT_FOUND. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + // Find user id from system id. + PortableServer::ObjectId user_id; + if (this->active_object_map ().find_user_id_using_system_id (system_id, + user_id) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + TAO_SERVANT_NOT_FOUND); + } + + TAO_Active_Object_Map::Map_Entry *entry = 0; + int result = this->active_object_map ().find_servant_using_system_id_and_user_id (system_id, + user_id, + servant, + entry); + if (result == 0) + { + // Success + return TAO_SERVANT_FOUND; + } + } + + // If the POA has the NON_RETAIN policy or has the RETAIN policy but + // didn't find a servant in the Active Object Map, the POA takes the + // following actions: + + // If the USE_ACTIVE_OBJECT_MAP_ONLY policy is in effect, the POA raises + // the OBJECT_NOT_EXIST system exception. + if (this->policies ().request_processing () == PortableServer::USE_ACTIVE_OBJECT_MAP_ONLY) + { + return TAO_SERVANT_NOT_FOUND; + } + +#if (TAO_HAS_MINIMUM_POA == 0) + + // If the POA has the USE_DEFAULT_SERVANT policy, a default servant + // has been associated with the POA, return TAO_DEFAULT_SERVANT. If + // no servant has been associated with the POA, return + // TAO_SERVANT_NOT_FOUND. + if (this->policies ().request_processing () == PortableServer::USE_DEFAULT_SERVANT) + { + if (this->default_servant_.in () == 0) + { + return TAO_SERVANT_NOT_FOUND; + } + else + { + // Success + return TAO_DEFAULT_SERVANT; + } + } + + // If the POA has the USE_SERVANT_MANAGER policy, a servant manager + // has been associated with the POA, return + // TAO_SERVANT_MANAGER. If no servant manager has been + // associated with the POA, return TAO_SERVANT_NOT_FOUND. + if (this->policies ().request_processing () == PortableServer::USE_SERVANT_MANAGER) + { + if (CORBA::is_nil (this->servant_activator_.in ()) && + CORBA::is_nil (this->servant_locator_.in ())) + { + return TAO_SERVANT_NOT_FOUND; + } + else + { + // Success + return TAO_SERVANT_MANAGER; + } + } + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + // Failure + return TAO_SERVANT_NOT_FOUND; +} + +PortableServer::Servant +TAO_POA::locate_servant_i (const char *operation, + const PortableServer::ObjectId &system_id, + TAO_Object_Adapter::Servant_Upcall &servant_upcall, + TAO_POA_Current_Impl &poa_current_impl, + CORBA::Environment &ACE_TRY_ENV) +{ + // If we have the RETAIN policy, convert/transform from system id to + // user id. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + if (this->active_object_map ().find_user_id_using_system_id (system_id, + poa_current_impl.object_id_) != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + } + else + { + // We have the NON_RETAIN policy, user id is the system id. + + // Smartly copy all the data; <poa_current_impl.object_id_> does + // not own the data. + poa_current_impl.object_id_.replace (system_id.maximum (), + system_id.length (), + ACE_const_cast (CORBA::Octet *, + system_id.get_buffer ()), + 0); + } + + // If the POA has the RETAIN policy, the POA looks in the Active + // Object Map to find if there is a servant associated with the + // Object Id value from the request. If such a servant exists, the + // POA invokes the appropriate method on the servant. + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + PortableServer::Servant servant = 0; + int result = this->active_object_map ().find_servant_using_system_id_and_user_id (system_id, + poa_current_impl.object_id (), + servant, + servant_upcall.active_object_map_entry_); + + if (result == 0) + { + // Increment the reference count. + ++servant_upcall.active_object_map_entry ()->reference_count_; + + // Success + return servant; + } + } + + // If the POA has the NON_RETAIN policy or has the RETAIN policy but + // didn't find a servant in the Active Object Map, the POA takes the + // following actions: + + // If the USE_ACTIVE_OBJECT_MAP_ONLY policy is in effect, the POA raises + // the OBJECT_NOT_EXIST system exception. + if (this->policies ().request_processing () == PortableServer::USE_ACTIVE_OBJECT_MAP_ONLY) + { + ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST (), + 0); + } + +#if (TAO_HAS_MINIMUM_POA == 0) + + // If the POA has the USE_DEFAULT_SERVANT policy, a default servant + // has been associated with the POA so the POA will invoke the + // appropriate method on that servant. If no servant has been + // associated with the POA, the POA raises the OBJ_ADAPTER system + // exception. + if (this->policies ().request_processing () == PortableServer::USE_DEFAULT_SERVANT) + { + PortableServer::Servant result = this->default_servant_.in (); + if (result == 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + else + { + // Success + return result; + } + } + + // If the POA has the USE_SERVANT_MANAGER policy, a servant manager + // has been associated with the POA so the POA will invoke incarnate + // or preinvoke on it to find a servant that may handle the + // request. (The choice of method depends on the NON_RETAIN or + // RETAIN policy of the POA.) If no servant manager has been + // associated with the POA, the POA raises the OBJ_ADAPTER system + // exception. + // + // If a servant manager is located and invoked, but the servant + // manager is not directly capable of incarnating the object, it + // (the servant manager) may deal with the circumstance in a variety + // of ways, all of which are the application's responsibility. Any + // system exception raised by the servant manager will be returned + // to the client in the reply. In addition to standard CORBA + // exceptions, a servant manager is capable of raising a + // ForwardRequest exception. This exception includes an object + // reference. + // + if (this->policies ().request_processing () == PortableServer::USE_SERVANT_MANAGER) + { + if (CORBA::is_nil (this->servant_activator_.in ()) && + CORBA::is_nil (this->servant_locator_.in ())) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + PortableServer::Servant servant = 0; + if (this->policies ().servant_retention () == PortableServer::RETAIN) + { + { + // A recursive thread lock without using a recursive + // thread lock. Non_Servant_Upcall has a magic + // constructor and destructor. We unlock the + // Object_Adapter lock for the duration of the servant + // activator upcalls; reacquiring once the upcalls + // complete. Even though we are releasing the lock, other + // threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has + // been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // @@ + // Invocations of incarnate on the servant manager are serialized. + // Invocations of etherealize on the servant manager are serialized. + // Invocations of incarnate and etherealize on the servant manager are mutually exclusive. + servant = this->servant_activator_->incarnate (poa_current_impl.object_id (), + this + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + if (servant == 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + } + + // If the incarnate operation returns a servant that is + // already active for a different Object Id and if the POA + // also has the UNIQUE_ID policy, the incarnate has violated + // the POA policy and is considered to be in error. The POA + // will raise an OBJ_ADAPTER system exception for the + // request. + if (this->policies ().id_uniqueness () == PortableServer::UNIQUE_ID && + this->is_servant_in_map (servant)) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // The POA enters the returned Servant value into the Active + // Object Map so that subsequent requests with the same + // ObjectId value will be delivered directly to that servant + // without invoking the servant manager. + int result = this->active_object_map ().rebind_using_user_id_and_system_id (servant, + poa_current_impl.object_id (), + system_id, + servant_upcall.active_object_map_entry_); + if (result != 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + else + { + // Increment the reference count. + ++servant_upcall.active_object_map_entry ()->reference_count_; + + // A recursive thread lock without using a recursive + // thread lock. Non_Servant_Upcall has a magic + // constructor and destructor. We unlock the + // Object_Adapter lock for the duration of the servant + // activator upcalls; reacquiring once the upcalls + // complete. Even though we are releasing the lock, + // other threads will not be able to make progress since + // <Object_Adapter::non_servant_upcall_in_progress_> has + // been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // If this operation causes the object to be activated, + // _add_ref is invoked at least once on the Servant + // argument before returning. Otherwise, the POA does + // not increment or decrement the reference count of the + // Servant passed to this function. + servant->_add_ref (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + // If we are a single threaded POA, set up the + // appropriate locking in the servant. + this->establish_servant_lock (servant); + + // Success + return servant; + } + } + else + // + // Don't retain servant + // + { + // A recursive thread lock without using a recursive thread + // lock. Non_Servant_Upcall has a magic constructor and + // destructor. We unlock the Object_Adapter lock for the + // duration of the servant activator upcalls; reacquiring + // once the upcalls complete. Even though we are releasing + // the lock, other threads will not be able to make progress + // since <Object_Adapter::non_servant_upcall_in_progress_> + // has been set. + TAO_Object_Adapter::Non_Servant_Upcall non_servant_upcall (this->object_adapter ()); + ACE_UNUSED_ARG (non_servant_upcall); + + // No serialization of invocations of preinvoke or + // postinvoke may be assumed; there may be multiple + // concurrent invocations of preinvoke for the same + // ObjectId. + // + // The same thread will be used to preinvoke the object, + // process the request, and postinvoke the object. + // + PortableServer::ServantLocator::Cookie cookie; + PortableServer::Servant servant = this->servant_locator_->preinvoke (poa_current_impl.object_id (), + this, + operation, + cookie + TAO_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + if (servant == 0) + { + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); + } + + // If we are a single threaded POA, set up the + // appropriate locking in the servant. + this->establish_servant_lock (servant); + + // Remember to invoke <postinvoke> + servant_upcall.using_servant_locator (); + + // Remember the cookie + servant_upcall.locator_cookie (cookie); + + // Remember operation name. + servant_upcall.operation (operation); + + // Success + return servant; + } + } +#else + ACE_UNUSED_ARG (operation); +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + // Failure + ACE_THROW_RETURN (CORBA::OBJ_ADAPTER (), + 0); +} + +/* static */ +int +TAO_POA::parse_key (const TAO_ObjectKey &key, + TAO_Object_Adapter::poa_name &poa_system_name, + PortableServer::ObjectId &system_id, + CORBA::Boolean &is_root, + CORBA::Boolean &is_persistent, + CORBA::Boolean &is_system_id, + TAO_Temporary_Creation_Time &poa_creation_time) +{ + // Start at zero. + CORBA::ULong starting_at = 0; + + // Get the object key octets. + const CORBA::Octet *key_data = key.get_buffer (); + +#if (TAO_NO_IOR_TABLE == 0) + // Skip the object key prefix since we have already checked for + // this. + starting_at += TAO_OBJECTKEY_PREFIX_SIZE; +#endif /* TAO_NO_IOR_TABLE */ + + // Check the root indicator. + char root_key_type = key_data[starting_at]; + if (root_key_type == TAO_POA::root_key_char ()) + { + is_root = 1; + } + else if (root_key_type == TAO_POA::non_root_key_char ()) + { + is_root = 0; + } + else + { + // Incorrect key + return -1; + } + + // Skip past the system id indicator + starting_at += TAO_POA::root_key_type_length (); + + // Check the system id indicator. + char system_id_key_type = key_data[starting_at]; + if (system_id_key_type == TAO_POA::system_id_key_char ()) + { + is_system_id = 1; + } + else if (system_id_key_type == TAO_POA::user_id_key_char ()) + { + is_system_id = 0; + } + else + { + // Incorrect key + return -1; + } + + // Skip past the system id indicator + starting_at += TAO_POA::system_id_key_type_length (); + + // Check the persistence indicator + char persistent_key_type = key_data[starting_at]; + if (persistent_key_type == TAO_POA::persistent_key_char ()) + { + is_persistent = 1; + } + else if (persistent_key_type == TAO_POA::transient_key_char ()) + { + is_persistent = 0; + } + else + { + // Incorrect key + return -1; + } + + // Skip past the persistent indicator + starting_at += TAO_POA::persistent_key_type_length (); + +#if (POA_NO_TIMESTAMP == 0) + // Grab the timestamp for transient POAs. + if (!is_persistent) + { + // Take the creation time for the timestamp + poa_creation_time.creation_time (key_data + starting_at); + + // Skip past the timestamp + starting_at += TAO_Creation_Time::creation_time_length (); + } +#else + ACE_UNUSED_ARG (poa_creation_time); +#endif /* POA_NO_TIMESTAMP */ + + // Calculate the size of the POA name. + CORBA::ULong poa_name_size = 0; + if (!is_persistent) + { + // Transient POAs have fixed size. + poa_name_size = TAO_Object_Adapter::transient_poa_name_size (); + } + else if (is_system_id) + { + // System ids have fixed size. + poa_name_size = key.length () - starting_at - TAO_Active_Object_Map::system_id_size (); + } + else + { + // Get the size from the object key. + ACE_OS::memcpy (&poa_name_size, + key_data + starting_at, + sizeof (poa_name_size)); + poa_name_size = ACE_NTOHL (poa_name_size); + + starting_at += sizeof (poa_name_size); + } + + // For non-root POAs, grab their name. + if (!is_root) + { + poa_system_name.replace (poa_name_size, + poa_name_size, + (CORBA::Octet *) key_data + starting_at, + 0); + + starting_at += poa_name_size; + } + + // The rest is the system id. + CORBA::ULong system_id_size = key.length () - starting_at; + + // Reset <system_id>. + system_id.replace (system_id_size, + system_id_size, + (CORBA::Octet *) key_data + starting_at, + 0); + + // Success + return 0; +} + +TAO_ObjectKey * +TAO_POA::create_object_key (const PortableServer::ObjectId &id) +{ + // Calculate the prefix size. + CORBA::ULong prefix_size = 0; +#if (TAO_NO_IOR_TABLE == 0) + prefix_size += TAO_OBJECTKEY_PREFIX_SIZE; +#endif /* TAO_NO_IOR_TABLE */ + + // If we are dealing with a persistent POA and user ids are being + // used, then we need to add the POA name length field to the object + // key. Otherwise, the POA name length can be calculated by looking + // at the remainder after extracting other parts of the key. + int add_poa_name_length = + this->persistent_ && + !this->system_id_; + + // Size required by the POA name. + CORBA::ULong poa_name = 0; + + // Calculate the space required for the POA name. + CORBA::ULong poa_name_length = this->system_name_->length (); + if (!this->root ()) + { + poa_name += poa_name_length; + } + + // Check if we need to added the length of the POA name. + if (add_poa_name_length) + { + poa_name += sizeof (poa_name_length); + } + + // Calculate the space required for the timestamp and the persistent + // byte. + CORBA::ULong creation_time = this->persistent_key_type_length (); +#if (POA_NO_TIMESTAMP == 0) + // Calculate the space required for the timestamp. + CORBA::ULong creation_time_length = TAO_Creation_Time::creation_time_length (); + if (!this->persistent_) + { + creation_time += creation_time_length; + } +#endif /* POA_NO_TIMESTAMP */ + + // Calculate the space required for the key. + CORBA::ULong buffer_size = + prefix_size + + this->root_key_type_length () + + this->system_id_key_type_length () + + creation_time + + poa_name + + id.length (); + + // Create the buffer for the key. + CORBA::Octet *buffer = TAO_ObjectKey::allocbuf (buffer_size); + + // Keeps track of where the next infomation goes; start at 0 byte. + CORBA::ULong starting_at = 0; + +#if (TAO_NO_IOR_TABLE == 0) + // Add the object key prefix. + ACE_OS::memcpy (&buffer[starting_at], + &objectkey_prefix[0], + TAO_OBJECTKEY_PREFIX_SIZE); + + starting_at += TAO_OBJECTKEY_PREFIX_SIZE; +#endif /* TAO_NO_IOR_TABLE */ + + // Copy the root byte. + buffer[starting_at] = (CORBA::Octet) this->root_key_type (); + starting_at += this->root_key_type_length (); + + // Copy the system id byte. + buffer[starting_at] = (CORBA::Octet) this->system_id_key_type (); + starting_at += this->system_id_key_type_length (); + + // Copy the persistence byte. + buffer[starting_at] = (CORBA::Octet) this->persistent_key_type (); + starting_at += this->persistent_key_type_length (); + +#if (POA_NO_TIMESTAMP == 0) + // Then copy the timestamp for transient POAs. + if (!this->persistent ()) + { + ACE_OS::memcpy (&buffer[starting_at], + this->creation_time_.creation_time (), + creation_time_length); + starting_at += creation_time_length; + } +#endif /* POA_NO_TIMESTAMP */ + + // Check if we need to added the length of the POA name. + if (add_poa_name_length) + { + poa_name_length = ACE_HTONL (poa_name_length); + ACE_OS::memcpy (&buffer[starting_at], + &poa_name_length, + sizeof (poa_name_length)); + starting_at += sizeof (poa_name_length); + } + + // Put the POA name into the key (for non-root POAs). + if (!this->root ()) + { + ACE_OS::memcpy (&buffer[starting_at], + this->system_name_->get_buffer (), + this->system_name_->length ()); + starting_at += this->system_name_->length (); + } + + // Then copy the object id into the key. + ACE_OS::memcpy (&buffer[starting_at], + id.get_buffer (), + id.length ()); + + // Create the key, giving the ownership of the buffer to the + // sequence. + TAO_ObjectKey *key = 0; + ACE_NEW_RETURN (key, + TAO_ObjectKey (buffer_size, + buffer_size, + buffer, + 1), + 0); + + return key; +} + +int +TAO_POA::is_poa_generated_id (const PortableServer::ObjectId &id) +{ + +#if defined (POA_NAME_IN_POA_GENERATED_ID) + + // Grab the buffer + const char *id_buffer = (const char *) id.get_buffer (); + + // Check to see if the POA name is the first part of the id + return + this->name_.length () < id.length () && + ACE_OS::strncmp (id_buffer, + this->name_.c_str (), + this->name_.length ()) == 0; + +#else /* POA_NAME_IN_POA_GENERATED_ID */ + + ACE_UNUSED_ARG (id); + return 1; + +#endif /* POA_NAME_IN_POA_GENERATED_ID */ +} + +void +TAO_POA::set_folded_name (void) +{ + CORBA::ULong length = 0; + CORBA::ULong parent_length = 0; + + if (this->parent_ != 0) + { + parent_length = this->parent_->folded_name ().length (); + length += parent_length; + } + + length += this->name_.length (); + length += TAO_POA::name_separator_length (); + + this->folded_name_.length (length); + CORBA::Octet *folded_name_buffer = this->folded_name_.get_buffer (); + + if (this->parent_ != 0) + { + ACE_OS::memcpy (folded_name_buffer, + this->parent_->folded_name ().get_buffer (), + parent_length); + } + + ACE_OS::memcpy (&folded_name_buffer[parent_length], + this->name_.c_str (), + this->name_.length ()); + + folded_name_buffer[length - TAO_POA::name_separator_length ()] = TAO_POA::name_separator (); +} + +PortableServer::ObjectId * +TAO_POA::string_to_ObjectId (const char *string) +{ + // Size of string + // + // We DO NOT include the zero terminator, as this is simply an + // artifact of the way strings are stored in C. + // + CORBA::ULong buffer_size = ACE_OS::strlen (string); + + // Create the buffer for the Id + CORBA::Octet *buffer = PortableServer::ObjectId::allocbuf (buffer_size); + + // Copy the contents + ACE_OS::memcpy (buffer, string, buffer_size); + + // Create and return a new ID + PortableServer::ObjectId *id = 0; + ACE_NEW_RETURN (id, + PortableServer::ObjectId (buffer_size, + buffer_size, + buffer, + 1), + 0); + + return id; +} + +PortableServer::ObjectId * +TAO_POA::string_to_ObjectId (const char *string, + int size) +{ + // Create the buffer for the Id + CORBA::Octet *buffer = PortableServer::ObjectId::allocbuf (size); + + // Copy the contents + ACE_OS::memcpy (buffer, string, size); + + // Create and return a new ID + PortableServer::ObjectId *id = 0; + ACE_NEW_RETURN (id, + PortableServer::ObjectId (size, + size, + buffer, + 1), + 0); + + return id; +} + +PortableServer::ObjectId * +TAO_POA::wstring_to_ObjectId (const CORBA::WChar *string) +{ + // Size of Id + // + // We DO NOT include the zero terminator, as this is simply an + // artifact of the way strings are stored in C. + // + CORBA::ULong string_length = ACE_OS::wslen (string); + + size_t buffer_size = string_length * sizeof (CORBA::WChar); + + // Create the buffer for the Id + CORBA::Octet *buffer = PortableServer::ObjectId::allocbuf (buffer_size); + + // Copy contents + ACE_OS::memcpy (buffer, string, buffer_size); + + // Create a new ID + PortableServer::ObjectId *id = 0; + ACE_NEW_RETURN (id, + PortableServer::ObjectId (buffer_size, + buffer_size, + buffer, + 1), + 0); + + return id; +} + +char * +TAO_POA::ObjectId_to_string (const PortableServer::ObjectId &id) +{ + // Create space + char * string = CORBA::string_alloc (id.length ()); + + // Copy the data + ACE_OS::memcpy (string, id.get_buffer (), id.length ()); + + // Null terminate the string + string[id.length ()] = '\0'; + + // Return string + return string; +} + +CORBA::WChar * +TAO_POA::ObjectId_to_wstring (const PortableServer::ObjectId &id) +{ + // Compute resulting wide string's length. + CORBA::ULong string_length = + id.length () / sizeof (CORBA::WChar) + 1; + + // Allocate an extra slot if the id's length is not "aligned" on a + // CORBA::WChar. + if (id.length () % sizeof (CORBA::WChar)) + string_length++; + + // Create space. + CORBA::WChar* string = CORBA::wstring_alloc (string_length); + + // Copy the data + ACE_OS::memcpy (string, + id.get_buffer (), + id.length ()); + + // Null terminate the string + string[string_length] = '\0'; + + // Return string. + return string; +} + +TAO_Object_Adapter & +TAO_POA::object_adapter (void) +{ + return *this->object_adapter_; +} + +#if (TAO_HAS_MINIMUM_POA == 0) + +PortableServer::ThreadPolicy_ptr +TAO_POA::create_thread_policy (PortableServer::ThreadPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Thread_Policy *thread_policy = 0; + ACE_NEW_THROW_EX (thread_policy, + TAO_Thread_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::ThreadPolicy::_nil ()); + + return thread_policy; +} + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + +PortableServer::LifespanPolicy_ptr +TAO_POA::create_lifespan_policy (PortableServer::LifespanPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Lifespan_Policy *lifespan_policy = 0; + ACE_NEW_THROW_EX (lifespan_policy, + TAO_Lifespan_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::LifespanPolicy::_nil ()); + + return lifespan_policy; +} + +PortableServer::IdUniquenessPolicy_ptr +TAO_POA::create_id_uniqueness_policy (PortableServer::IdUniquenessPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Id_Uniqueness_Policy *id_uniqueness_policy = 0; + ACE_NEW_THROW_EX (id_uniqueness_policy, + TAO_Id_Uniqueness_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::IdUniquenessPolicy::_nil ()); + + return id_uniqueness_policy; +} + +PortableServer::IdAssignmentPolicy_ptr +TAO_POA::create_id_assignment_policy (PortableServer::IdAssignmentPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Id_Assignment_Policy *id_assignment_policy = 0; + ACE_NEW_THROW_EX (id_assignment_policy, + TAO_Id_Assignment_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::IdAssignmentPolicy::_nil ()); + + return id_assignment_policy; +} + +#if (TAO_HAS_MINIMUM_POA == 0) + +PortableServer::ImplicitActivationPolicy_ptr +TAO_POA::create_implicit_activation_policy (PortableServer::ImplicitActivationPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Implicit_Activation_Policy *implicit_activation_policy = 0; + ACE_NEW_THROW_EX (implicit_activation_policy, + TAO_Implicit_Activation_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::ImplicitActivationPolicy::_nil ()); + + return implicit_activation_policy; +} + +PortableServer::ServantRetentionPolicy_ptr +TAO_POA::create_servant_retention_policy (PortableServer::ServantRetentionPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Servant_Retention_Policy *servant_retention_policy = 0; + ACE_NEW_THROW_EX (servant_retention_policy, + TAO_Servant_Retention_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::ServantRetentionPolicy::_nil ()); + + return servant_retention_policy; +} + +PortableServer::RequestProcessingPolicy_ptr +TAO_POA::create_request_processing_policy (PortableServer::RequestProcessingPolicyValue value, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Request_Processing_Policy *request_processing_policy = 0; + ACE_NEW_THROW_EX (request_processing_policy, + TAO_Request_Processing_Policy (value), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (PortableServer::RequestProcessingPolicy::_nil ()); + + return request_processing_policy; +} + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + +#if (TAO_HAS_MINIMUM_POA == 0) + +TAO_Thread_Policy::TAO_Thread_Policy (PortableServer::ThreadPolicyValue value) + : value_ (value) +{ +} + +PortableServer::ThreadPolicyValue +TAO_Thread_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Thread_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Thread_Policy *thread_policy_copy = 0; + ACE_NEW_THROW_EX (thread_policy_copy, + TAO_Thread_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return thread_policy_copy; +} + +void +TAO_Thread_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Thread_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::THREAD_POLICY_ID; +} + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + +TAO_Lifespan_Policy::TAO_Lifespan_Policy (PortableServer::LifespanPolicyValue value) + : value_ (value) +{ +} + +PortableServer::LifespanPolicyValue +TAO_Lifespan_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Lifespan_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Lifespan_Policy *lifespan_policy_copy = 0; + ACE_NEW_THROW_EX (lifespan_policy_copy, + TAO_Lifespan_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return lifespan_policy_copy; +} + +void +TAO_Lifespan_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Lifespan_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::LIFESPAN_POLICY_ID; +} + +TAO_Id_Uniqueness_Policy::TAO_Id_Uniqueness_Policy (PortableServer::IdUniquenessPolicyValue value) + : value_ (value) +{ +} + +PortableServer::IdUniquenessPolicyValue +TAO_Id_Uniqueness_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Id_Uniqueness_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Id_Uniqueness_Policy *id_uniqueness_policy_copy = 0; + ACE_NEW_THROW_EX (id_uniqueness_policy_copy, + TAO_Id_Uniqueness_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return id_uniqueness_policy_copy; +} + +void +TAO_Id_Uniqueness_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Id_Uniqueness_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::ID_UNIQUENESS_POLICY_ID; +} + +TAO_Id_Assignment_Policy::TAO_Id_Assignment_Policy (PortableServer::IdAssignmentPolicyValue value) + : value_ (value) +{ +} + +PortableServer::IdAssignmentPolicyValue +TAO_Id_Assignment_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Id_Assignment_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Id_Assignment_Policy *id_assignment_policy_copy = 0; + ACE_NEW_THROW_EX (id_assignment_policy_copy, + TAO_Id_Assignment_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return id_assignment_policy_copy; +} + +void +TAO_Id_Assignment_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Id_Assignment_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::ID_ASSIGNMENT_POLICY_ID; +} + +#if (TAO_HAS_MINIMUM_POA == 0) + +TAO_Implicit_Activation_Policy::TAO_Implicit_Activation_Policy (PortableServer::ImplicitActivationPolicyValue value) + : value_ (value) +{ +} + +PortableServer::ImplicitActivationPolicyValue +TAO_Implicit_Activation_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Implicit_Activation_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Implicit_Activation_Policy *implicit_activation_policy_copy = 0; + ACE_NEW_THROW_EX (implicit_activation_policy_copy, + TAO_Implicit_Activation_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return implicit_activation_policy_copy; +} + +void +TAO_Implicit_Activation_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Implicit_Activation_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::IMPLICIT_ACTIVATION_POLICY_ID; +} + +TAO_Servant_Retention_Policy::TAO_Servant_Retention_Policy (PortableServer::ServantRetentionPolicyValue value) + : value_ (value) +{ +} + +PortableServer::ServantRetentionPolicyValue +TAO_Servant_Retention_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Servant_Retention_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Servant_Retention_Policy *servant_retention_policy_copy = 0; + ACE_NEW_THROW_EX (servant_retention_policy_copy, + TAO_Servant_Retention_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return servant_retention_policy_copy; +} + +void +TAO_Servant_Retention_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Servant_Retention_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::SERVANT_RETENTION_POLICY_ID; +} + +TAO_Request_Processing_Policy::TAO_Request_Processing_Policy (PortableServer::RequestProcessingPolicyValue value) + : value_ (value) +{ +} + +PortableServer::RequestProcessingPolicyValue +TAO_Request_Processing_Policy::value (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return this->value_; +} + +CORBA::Policy_ptr +TAO_Request_Processing_Policy::copy (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + TAO_Request_Processing_Policy *request_processing_policy_copy = 0; + ACE_NEW_THROW_EX (request_processing_policy_copy, + TAO_Request_Processing_Policy (this->value_), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (CORBA::Policy::_nil ()); + + return request_processing_policy_copy; +} + +void +TAO_Request_Processing_Policy::destroy (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +CORBA::PolicyType +TAO_Request_Processing_Policy::policy_type (CORBA::Environment &) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return PortableServer::REQUEST_PROCESSING_POLICY_ID; +} + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + +TAO_POA_Policies::TAO_POA_Policies (TAO_ORB_Core &orb_core, + CORBA::Environment &ACE_TRY_ENV) + : thread_ (PortableServer::ORB_CTRL_MODEL), + lifespan_ (PortableServer::TRANSIENT), + id_uniqueness_ (PortableServer::UNIQUE_ID), + id_assignment_ (PortableServer::SYSTEM_ID), + implicit_activation_ (PortableServer::NO_IMPLICIT_ACTIVATION), + servant_retention_ (PortableServer::RETAIN), + request_processing_ (PortableServer::USE_ACTIVE_OBJECT_MAP_ONLY), + priority_model_ (TAO_POA_Policies::CLIENT_PROPAGATED), + server_priority_ (TAO_INVALID_PRIORITY), + +#if (TAO_HAS_RT_CORBA == 1) + + server_protocol_ (0), + +#endif /* TAO_HAS_RT_CORBA == 1 */ + + client_exposed_fixed_policies_ () +{ + +#if (TAO_HAS_RT_CORBA == 1) + + RTCORBA::PriorityModelPolicy_var priority_model = + orb_core.priority_model (); + + if (!CORBA::is_nil (priority_model.in ())) + { + RTCORBA::PriorityModel rt_priority_model = + priority_model->priority_model (ACE_TRY_ENV); + ACE_CHECK; + + this->priority_model_ = + TAO_POA_Policies::PriorityModel (rt_priority_model); + + this->server_priority_ = + priority_model->server_priority (ACE_TRY_ENV); + ACE_CHECK; + } + + TAO_ServerProtocolPolicy *server_protocol = + orb_core.server_protocol (); + + if (server_protocol != 0) + { + this->server_protocol (server_protocol); + server_protocol->_remove_ref (); + } + +#else + + ACE_UNUSED_ARG (orb_core); + ACE_UNUSED_ARG (ACE_TRY_ENV); + +#endif /* TAO_HAS_RT_CORBA == 1 */ + +} + +TAO_POA_Policies::TAO_POA_Policies (const TAO_POA_Policies &rhs) + : thread_ (rhs.thread ()), + lifespan_ (rhs.lifespan ()), + id_uniqueness_ (rhs.id_uniqueness ()), + id_assignment_ (rhs.id_assignment ()), + implicit_activation_ (rhs.implicit_activation ()), + servant_retention_ (rhs.servant_retention ()), + request_processing_ (rhs.request_processing ()), + priority_model_ (rhs.priority_model ()), + server_priority_ (rhs.server_priority ()), + +#if (TAO_HAS_RT_CORBA == 1) + + server_protocol_ (0), + +#endif /* TAO_HAS_RT_CORBA == 1 */ + + client_exposed_fixed_policies_ ( rhs.client_exposed_fixed_policies ()) +{ + +#if (TAO_HAS_RT_CORBA == 1) + + this->server_protocol (rhs.server_protocol ()); + +#endif /* TAO_HAS_RT_CORBA == 1 */ + +} + +TAO_POA_Policies::~TAO_POA_Policies (void) +{ + for (CORBA::ULong i = 0; + i < this->client_exposed_fixed_policies_.length (); + ++i) + { + ACE_TRY_NEW_ENV + { + this->client_exposed_fixed_policies_[i]->destroy (ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // Ignore exceptions + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "TAO_POA_Policies::~TAO_POA_Policies"); + } + ACE_ENDTRY; + } + +#if (TAO_HAS_RT_CORBA == 1) + + this->server_protocol (0); + +#endif /* TAO_HAS_RT_CORBA == 1 */ + +} + +void +TAO_POA_Policies::parse_policies (const CORBA::PolicyList &policies, + CORBA::Environment &ACE_TRY_ENV) +{ + for (CORBA::ULong i = 0; + i < policies.length (); + i++) + { + this->parse_policy (policies[i], + ACE_TRY_ENV); + ACE_CHECK; + } + + if (this->validity_check () == -1) + { + ACE_THROW (PortableServer::POA::InvalidPolicy ()); + } +} + +int +TAO_POA_Policies::validity_check (void) +{ + // The NON_RETAIN policy requires either the USE_DEFAULT_SERVANT or + // USE_SERVANT_MANAGER policies. + if (this->servant_retention_ == PortableServer::NON_RETAIN) + if (this->request_processing_ != PortableServer::USE_SERVANT_MANAGER && + this->request_processing_ != PortableServer::USE_DEFAULT_SERVANT) + return -1; + + // USE_ACTIVE_OBJECT_MAP_ONLY requires the RETAIN policy. + if (this->request_processing_ == PortableServer::USE_ACTIVE_OBJECT_MAP_ONLY) + if (this->servant_retention_ != PortableServer::RETAIN) + return -1; + + // USE_DEFAULT_SERVANT requires the MULTIPLE_ID policy. + if (this->request_processing_ == PortableServer::USE_DEFAULT_SERVANT) + if (this->id_uniqueness_ != PortableServer::MULTIPLE_ID) + return -1; + + // IMPLICIT_ACTIVATION requires the SYSTEM_ID and RETAIN policies. + if (this->implicit_activation_ == PortableServer::IMPLICIT_ACTIVATION) + if (this->servant_retention_ != PortableServer::RETAIN || + this->id_assignment_ != PortableServer::SYSTEM_ID) + return -1; + + int result = 0; + + result = this->validate_priority_model (); + if (result != 0) + return result; + + result = this->validate_server_protocol (); + if (result != 0) + return result; + + return 0; +} + +int +TAO_POA_Policies::validate_priority_model (void) +{ + return 0; +} + +int +TAO_POA_Policies::validate_server_protocol (void) +{ + return 0; +} + +#if (TAO_HAS_RT_CORBA == 1) + +int +TAO_POA_Policies::validate_client_protocol (RTCORBA::ClientProtocolPolicy_ptr) +{ + return 0; +} + +int +TAO_POA_Policies::validate_priority_bands (RTCORBA::PriorityBandedConnectionPolicy_ptr) +{ + return 0; +} + +#endif /* TAO_HAS_RT_CORBA == 1 */ + +void +TAO_POA_Policies::parse_policy (const CORBA::Policy_ptr policy, + CORBA::Environment &ACE_TRY_ENV) +{ + +#if (TAO_HAS_MINIMUM_POA == 0) + + PortableServer::ThreadPolicy_var thread + = PortableServer::ThreadPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (thread.in ())) + { + this->thread_ = thread->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + PortableServer::LifespanPolicy_var lifespan + = PortableServer::LifespanPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (lifespan.in ())) + { + this->lifespan_ = lifespan->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + PortableServer::IdUniquenessPolicy_var id_uniqueness + = PortableServer::IdUniquenessPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (id_uniqueness.in ())) + { + this->id_uniqueness_ = id_uniqueness->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + PortableServer::IdAssignmentPolicy_var id_assignment + = PortableServer::IdAssignmentPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (id_assignment.in ())) + { + this->id_assignment_ = id_assignment->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + +#if (TAO_HAS_MINIMUM_POA == 0) + + PortableServer::ImplicitActivationPolicy_var implicit_activation + = PortableServer::ImplicitActivationPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (implicit_activation.in ())) + { + this->implicit_activation_ = implicit_activation->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + PortableServer::ServantRetentionPolicy_var servant_retention + = PortableServer::ServantRetentionPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (servant_retention.in ())) + { + this->servant_retention_ = servant_retention->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + PortableServer::RequestProcessingPolicy_var request_processing + = PortableServer::RequestProcessingPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (request_processing.in ())) + { + this->request_processing_ = request_processing->value (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + +#if (TAO_HAS_RT_CORBA == 1) + + RTCORBA::PriorityModelPolicy_var priority_model + = RTCORBA::PriorityModelPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (priority_model.in ())) + { + RTCORBA::PriorityModel rt_priority_model = + priority_model->priority_model (ACE_TRY_ENV); + ACE_CHECK; + + this->priority_model_ = + TAO_POA_Policies::PriorityModel (rt_priority_model); + + this->server_priority_ = + priority_model->server_priority (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + RTCORBA::ClientProtocolPolicy_var client_protocol + = RTCORBA::ClientProtocolPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (client_protocol.in ())) + { + int result = + this->validate_client_protocol (client_protocol.in ()); + + if (result != 0) + ACE_THROW (PortableServer::POA::InvalidPolicy ()); + + CORBA::ULong current_length = + this->client_exposed_fixed_policies_.length (); + + this->client_exposed_fixed_policies_.length (current_length + 1); + + this->client_exposed_fixed_policies_[current_length] = + client_protocol->copy (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + RTCORBA::PriorityBandedConnectionPolicy_var priority_bands + = RTCORBA::PriorityBandedConnectionPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (priority_bands.in ())) + { + int result = + this->validate_priority_bands (priority_bands.in ()); + + if (result != 0) + ACE_THROW (PortableServer::POA::InvalidPolicy ()); + + CORBA::ULong current_length = + this->client_exposed_fixed_policies_.length (); + + this->client_exposed_fixed_policies_.length (current_length + 1); + + this->client_exposed_fixed_policies_[current_length] = + priority_bands->copy (ACE_TRY_ENV); + ACE_CHECK; + + return; + } + + RTCORBA::ServerProtocolPolicy_var server_protocol + = RTCORBA::ServerProtocolPolicy::_narrow (policy, + ACE_TRY_ENV); + ACE_CHECK; + + if (!CORBA::is_nil (server_protocol.in ())) + { + TAO_ServerProtocolPolicy *server_protocol_i = + ACE_dynamic_cast (TAO_ServerProtocolPolicy *, + server_protocol.in ()); + + this->server_protocol (server_protocol_i); + + return; + } + +#endif /* TAO_HAS_RT_CORBA == 1 */ + + ACE_THROW (PortableServer::POA::InvalidPolicy ()); +} + +#if (TAO_HAS_RT_CORBA == 1) + +void +TAO_POA_Policies::server_protocol (TAO_ServerProtocolPolicy *policy) +{ + if (this->server_protocol_) + { + this->server_protocol_->destroy (); + CORBA::release (this->server_protocol_); + this->server_protocol_ = 0; + } + + if (policy) + { + ACE_NEW (this->server_protocol_, + TAO_ServerProtocolPolicy (*policy)); + } + +} + +#endif /* TAO_HAS_RT_CORBA == 1 */ + +#if (TAO_HAS_MINIMUM_POA == 0) + +TAO_Adapter_Activator::TAO_Adapter_Activator (PortableServer::POAManager_ptr poa_manager) + : poa_manager_ (PortableServer::POAManager::_duplicate (poa_manager)) +{ +} + +CORBA::Boolean +TAO_Adapter_Activator::unknown_adapter (PortableServer::POA_ptr parent, + const char *name, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // Default policies + CORBA::PolicyList default_policies; + + // This assumes that the lock on the parent is recursive + PortableServer::POA_var child = parent->create_POA (name, + this->poa_manager_.in (), + default_policies, + ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + ACE_TRY + { + child->the_activator (this, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + child->destroy (1, + 1, + ACE_TRY_ENV); + + return 0; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + // Finally everything is fine + return 1; +} + +#endif /* TAO_HAS_MINIMUM_POA == 0 */ + + +#if (TAO_HAS_RT_CORBA == 1) + +// @@ We may want to move this class to its own file, but it is only +// used here. + +class TAO_Server_Policy_Acceptor_Filter : public TAO_Acceptor_Filter +{ +public: + TAO_Server_Policy_Acceptor_Filter (RTCORBA::ProtocolList &protocols); + + virtual int evaluate (TAO_Acceptor *acceptor); + +private: + RTCORBA::ProtocolList &protocols_; +}; + +TAO_Server_Policy_Acceptor_Filter:: +TAO_Server_Policy_Acceptor_Filter (RTCORBA::ProtocolList &protocols) + : protocols_ (protocols) +{ +} + +int +TAO_Server_Policy_Acceptor_Filter::evaluate (TAO_Acceptor *acceptor) +{ + for (CORBA::ULong j = 0; + j != this->protocols_.length (); + ++j) + { + if (acceptor->tag () == this->protocols_[j].protocol_type) + return 1; + } + return 0; +} +#endif /* TAO_HAS_RT_CORBA == 1 */ + +CORBA::Object_ptr +TAO_POA::key_to_object (const TAO_ObjectKey &key, + const char *type_id, + TAO_ServantBase *servant, + CORBA::Boolean collocated, + CORBA::Short priority, + CORBA_Environment &ACE_TRY_ENV) +{ + // Check if the ORB is still running, otherwise throw an exception. + // @@ What if the ORB was destroyed? In that case we shouldn't even + // get here! + this->orb_core_.check_shutdown (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + CORBA::Object_ptr obj = CORBA::Object::_nil (); + + // + // ImplRepo related. + // +#if (TAO_HAS_MINIMUM_CORBA == 0) + + if (this->use_imr_ + && this->policies_.lifespan () == PortableServer::PERSISTENT) + { + // Check to see if we alter the IOR. + CORBA::Object_var imr = + this->orb_core ().implrepo_service (); + + if (CORBA::is_nil (imr.in ()) + || !imr->_stubobj () + || !imr->_stubobj ()->profile_in_use ()) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "Invalid Implementation Repository IOR, skipping IMRification\n")); + goto orbkey; + } + + CORBA::String_var imr_str = + imr->_stubobj ()->profile_in_use ()->to_string (ACE_TRY_ENV); + ACE_CHECK_RETURN (obj); + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "IMR IOR = \n%s\n", + imr_str.in ())); + char *pos = ACE_OS::strstr (imr_str.inout (), + "://"); + pos = ACE_OS::strchr (pos + 3, + imr->_stubobj ()->profile_in_use ()->object_key_delimiter ()); + if (pos) + pos[1] = 0; // Crop the string. + else + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + "Could not parse IMR IOR, skipping IMRification\n")); + goto orbkey; + } + + ACE_CString ior (imr_str.in ()); + + // Add the key. + + CORBA::String_var key_str; + TAO_ObjectKey::encode_sequence_to_string (key_str.inout (), key); + + ior += key_str.in (); + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + "IMR-ified IOR = \n%s\n", + ior.c_str ())); + + obj = + this->orb_core_.orb ()->string_to_object (ior.c_str (), ACE_TRY_ENV); + ACE_CHECK_RETURN (obj); + + return obj; + } + +orbkey: +#endif /* TAO_HAS_MINIMUM_CORBA */ + + TAO_Stub *data = + this->key_to_stub_i (key, type_id, priority, ACE_TRY_ENV); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + + TAO_Stub_Auto_Ptr safe_data (data); + + CORBA::Object_ptr tmp; + + if (this->orb_core_.optimize_collocation_objects ()) + { + ACE_NEW_THROW_EX (tmp, + TAO_Collocated_Object (safe_data.get (), + collocated, + servant), + CORBA::INTERNAL ()); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + } + else + { + ACE_NEW_THROW_EX (tmp, + CORBA_Object (safe_data.get (), + collocated), + CORBA::INTERNAL ()); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + } + + safe_data.get ()->servant_orb (this->orb_core_.orb ()); + + // Transfer ownership to the Object. + (void) safe_data.release (); + + return tmp; +} + +TAO_Stub * +TAO_POA::key_to_stub (const TAO_ObjectKey &key, + const char *type_id, + CORBA::Short priority, + CORBA_Environment &ACE_TRY_ENV) +{ + // Check if the ORB is still running, otherwise throw an exception. + // @@ What if the ORB was destroyed? In that case we shouldn't even + // get here! + this->orb_core_.check_shutdown (ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + return this->key_to_stub_i (key, type_id, priority, ACE_TRY_ENV); +} + +TAO_Stub * +TAO_POA::key_to_stub_i (const TAO_ObjectKey &key, + const char *type_id, + CORBA::Short priority, + CORBA_Environment &ACE_TRY_ENV) +{ + CORBA::PolicyList_var client_exposed_policies = + this->client_exposed_policies (priority, + ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + // By default all the acceptors are useful, but with RT CORBA we + // must only accept the protocols configured in the POA. + TAO_Acceptor_Filter *filter = 0; + +#if (TAO_HAS_RT_CORBA == 1) + + // RTCORBA 1.0, Section 4.15.1: ServerProtocolPolicy determines + // which protocols get included into IOR and in what order. + TAO_ServerProtocolPolicy *policy = + this->policies ().server_protocol (); + RTCORBA::ProtocolList & protocols = policy->protocols_rep (); + + TAO_Server_Policy_Acceptor_Filter real_filter (protocols); + filter = &real_filter; + +#endif /* TAO_HAS_RT_CORBA == 1 */ + + TAO_Stub *data = + this->orb_core_.create_stub_object (key, + type_id, + client_exposed_policies._retn (), + filter, + ACE_TRY_ENV); + ACE_CHECK_RETURN (0); + + return data; +} + +CORBA::PolicyList * +TAO_POA::client_exposed_policies (CORBA::Short object_priority, + CORBA_Environment &ACE_TRY_ENV) +{ + const CORBA::PolicyList &client_exposed_fixed_policies = + this->policies ().client_exposed_fixed_policies (); + + CORBA::PolicyList *client_exposed_policies = 0; + ACE_NEW_THROW_EX (client_exposed_policies, + CORBA::PolicyList (), + CORBA::NO_MEMORY (TAO_DEFAULT_MINOR_CODE, + CORBA::COMPLETED_NO)); + ACE_CHECK_RETURN (0); + + client_exposed_policies->length (client_exposed_fixed_policies.length ()); + + for (CORBA::ULong i = 0; + i < client_exposed_fixed_policies.length (); + ++i) + (*client_exposed_policies)[i] = + client_exposed_fixed_policies[i]->copy (); + +#if (TAO_HAS_RT_CORBA == 1) + + CORBA::Short poa_priority = + this->policies ().server_priority (); + + if (poa_priority != TAO_INVALID_PRIORITY) + { + TAO_POA_Policies::PriorityModel priority_model = + this->policies ().priority_model (); + + CORBA::Short priority; + if (priority_model == TAO_POA_Policies::CLIENT_PROPAGATED) + priority = poa_priority; + else + { + if (object_priority == TAO_INVALID_PRIORITY) + priority = poa_priority; + else + priority = object_priority; + } + + TAO_PriorityModelPolicy *priority_model_policy; + ACE_NEW_THROW_EX (priority_model_policy, + TAO_PriorityModelPolicy (RTCORBA::PriorityModel (priority_model), + priority), + CORBA::NO_MEMORY (TAO_DEFAULT_MINOR_CODE, + CORBA::COMPLETED_NO)); + ACE_CHECK_RETURN (0); + + CORBA::ULong current_length = client_exposed_policies->length (); + client_exposed_policies->length (current_length + 1); + (*client_exposed_policies)[current_length] = priority_model_policy; + } + +#else /* TAO_HAS_RT_CORBA == 1 */ + + ACE_UNUSED_ARG (object_priority); + +#endif /* TAO_HAS_RT_CORBA == 1 */ + + return client_exposed_policies; +} + +// +// ImplRepo related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) + +void +TAO_POA::imr_notify_startup (CORBA_Environment &ACE_TRY_ENV) +{ + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "Notifying IMR of startup\n")); + + CORBA::Object_var imr = this->orb_core ().implrepo_service (); + + if (CORBA::is_nil (imr.in ())) + return; + + ACE_NEW_THROW_EX (this->server_object_, + ServerObject_i (this->orb_core_.orb ()), + CORBA::NO_MEMORY ()); + ACE_CHECK; + + // Activate the servant in the root poa. + TAO_POA *root_poa = this->object_adapter ().root_poa (); + PortableServer::ObjectId_var id = + root_poa->activate_object_i (this->server_object_, + TAO_INVALID_PRIORITY, + ACE_TRY_ENV); + ACE_CHECK; + + CORBA::Object_var obj = root_poa->id_to_reference_i (id.in (), + ACE_TRY_ENV); + ACE_CHECK; + + ImplementationRepository::ServerObject_var svr + = ImplementationRepository::ServerObject::_narrow (obj.in (), + ACE_TRY_ENV); + ACE_CHECK; + + if (!svr->_stubobj () || !svr->_stubobj ()->profile_in_use ()) + { + ACE_ERROR ((LM_ERROR, "Invalid ServerObject, bailing out.\n")); + return; + } + + CORBA::String_var svr_str = + svr->_stubobj ()->profile_in_use ()->to_string (ACE_TRY_ENV); + ACE_CHECK; + + char *pos = ACE_OS::strstr (svr_str.inout (), "://"); + + pos = ACE_OS::strchr (pos + 3, + svr->_stubobj ()->profile_in_use ()->object_key_delimiter ()); + + if (pos) + *(pos + 1) = 0; // Crop the string + else + { + ACE_ERROR ((LM_ERROR, + "Could not parse ServerObject IOR, bailing out.\n")); + return; + } + + ACE_CString ior (svr_str.in ()); + + CORBA::String_var curr_addr (svr_str); + + ImplementationRepository::Administration_var imr_admin = + ImplementationRepository::Administration::_narrow (imr.in (), ACE_TRY_ENV); + ACE_CHECK; + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "Informing IMR that we are running at: %s\n", curr_addr.in ())); + + imr_admin->server_is_running (this->name ().c_str (), + curr_addr.in (), + svr.in (), + ACE_TRY_ENV); + ACE_CHECK; + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "Successfully notified IMR of Startup\n")); + +} + +void +TAO_POA::imr_notify_shutdown (void) +{ + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, "Notifing IMR of Shutdown\n")); + + // Notify the Implementation Repository about shutting down. + CORBA::Object_var imr = this->orb_core ().implrepo_service (); + + // Check to see if there was an imr returned. If none, return ourselves. + if (CORBA::is_nil (imr.in ())) + return; + + ACE_TRY_NEW_ENV + { + // Get the IMR's administrative object and call shutting_down on it + ImplementationRepository::Administration_var imr_admin = + ImplementationRepository::Administration::_narrow (imr.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + + imr_admin->server_is_shutting_down (this->the_name (), ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Server_i::init"); + // Ignore exceptions + } + ACE_ENDTRY; +} + +#endif /* TAO_HAS_MINIMUM_CORBA */ + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Array<PortableServer::ObjectId>; +template class ACE_Array_Base<PortableServer::ObjectId>; + +// +// Forwarding related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) + +template class ACE_Auto_Basic_Ptr<TAO_Forwarding_Servant>; +template class auto_ptr<TAO_Forwarding_Servant>; + +#endif /* TAO_HAS_MINIMUM_CORBA */ + +//template class ACE_Auto_Basic_Ptr<TAO_Active_Object_Map_Iterator_Impl>; +template class ACE_Auto_Basic_Ptr<TAO_POA>; +template class ACE_Auto_Basic_Ptr<TAO_Active_Object_Map>; +template class ACE_Auto_Basic_Ptr<TAO_POA_Manager>; +template class ACE_Map_Entry<TAO_Unbounded_Sequence<unsigned char>, TAO_ServantBase *>; +template class ACE_Hash_Map_Entry<ACE_CString, TAO_POA *>; +template class ACE_Hash_Map_Manager<ACE_CString, TAO_POA *, ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator<ACE_CString, TAO_POA *, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator<ACE_CString, TAO_POA *, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; +template class ACE_Write_Guard<ACE_Lock>; +template class ACE_Read_Guard<ACE_Lock>; + +//template class auto_ptr<TAO_Active_Object_Map_Iterator_Impl>; +template class auto_ptr<TAO_POA>; +template class auto_ptr<TAO_Active_Object_Map>; +template class auto_ptr<TAO_POA_Manager>; +template class ACE_Node<TAO_POA *>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate ACE_Array<PortableServer::ObjectId> +#pragma instantiate ACE_Array_Base<PortableServer::ObjectId> + +// +// Forwarding related. +// +#if (TAO_HAS_MINIMUM_CORBA == 0) + +#pragma instantiate ACE_Auto_Basic_Ptr<TAO_Forwarding_Servant> +#pragma instantiate auto_ptr<TAO_Forwarding_Servant> + +#endif /* TAO_HAS_MINIMUM_CORBA */ + +//#pragma instantiate ACE_Auto_Basic_Ptr<TAO_Active_Object_Map_Iterator_Impl> +#pragma instantiate ACE_Auto_Basic_Ptr<TAO_POA> +#pragma instantiate ACE_Auto_Basic_Ptr<TAO_Active_Object_Map> +#pragma instantiate ACE_Auto_Basic_Ptr<TAO_POA_Manager> +#pragma instantiate ACE_Map_Entry<TAO_Unbounded_Sequence<unsigned char>, TAO_ServantBase *> +#pragma instantiate ACE_Hash_Map_Entry<ACE_CString, TAO_POA *> +#pragma instantiate ACE_Hash_Map_Manager<ACE_CString, TAO_POA *, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator<ACE_CString, TAO_POA *, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator<ACE_CString, TAO_POA *, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<ACE_CString, TAO_POA *, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> +#pragma instantiate ACE_Write_Guard<ACE_Lock> +#pragma instantiate ACE_Read_Guard<ACE_Lock> + +//#pragma instantiate auto_ptr<TAO_Active_Object_Map_Iterator_Impl> +#pragma instantiate auto_ptr<TAO_POA> +#pragma instantiate auto_ptr<TAO_Active_Object_Map> +#pragma instantiate auto_ptr<TAO_POA_Manager> +#pragma instantiate ACE_Node<TAO_POA *> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ |