diff options
Diffstat (limited to 'TAO/CIAO/ciao/Container_Impl.cpp')
-rw-r--r-- | TAO/CIAO/ciao/Container_Impl.cpp | 567 |
1 files changed, 567 insertions, 0 deletions
diff --git a/TAO/CIAO/ciao/Container_Impl.cpp b/TAO/CIAO/ciao/Container_Impl.cpp new file mode 100644 index 00000000000..ac5fc047693 --- /dev/null +++ b/TAO/CIAO/ciao/Container_Impl.cpp @@ -0,0 +1,567 @@ +// $Id$ +#include "Container_Impl.h" +#include "CCM_ComponentC.h" // for calling StandardConfigurator interface + +#include "orbsvcs/CosNamingC.h" + +#if !defined (__ACE_INLINE__) +# include "Container_Impl.inl" +#endif /* __ACE_INLINE__ */ + +CIAO::Container_Impl::~Container_Impl () +{ + // @@ remove all components and home? + delete this->container_; +} + +PortableServer::POA_ptr +CIAO::Container_Impl::_default_POA (void) +{ + return PortableServer::POA::_duplicate (this->poa_.in ()); +} + + /////////////////////////////////////////////////////////////// + +CORBA::Long +CIAO::Container_Impl::init (const ::Deployment::Properties &properties + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + // @@ Gan/Jai, see how this init can create many instances of the + // same container? Neither thread safe or single entity safe. + this->properties_ = properties; + + // @@ Initialize container and create the internal container + // implementation that actually interacts with installed + // homes/components. + + // @@ We will need a container factory here later on when we support + // more kinds of container implementations. + + // @@Jai, what is the condition to create an upgradeable container? + // Where is it getting created and how? Need to address that. + + ACE_NEW_THROW_EX (this->container_, + CIAO::Session_Container (this->orb_.in (), this), + CORBA::INTERNAL ()); + ACE_CHECK_RETURN (-1); + + return this->container_->init (0, + 0 + ACE_ENV_ARG_PARAMETER); +} + + +Deployment::ComponentInfos * +CIAO::Container_Impl::install ( + const ::Deployment::ContainerImplementationInfo & container_impl_info + ACE_ENV_ARG_DECL + ) + ACE_THROW_SPEC ((CORBA::SystemException, + ::Deployment::UnknownImplId, + ::Deployment::ImplEntryPointNotFound, + ::Deployment::InstallationFailure, + ::Components::InvalidConfiguration)) +{ + Deployment::ComponentInfos_var retv; + ACE_TRY + { + ACE_NEW_THROW_EX (retv, + Deployment::ComponentInfos, + CORBA::NO_MEMORY ()); + ACE_TRY_CHECK; + + // Get the ComponentImplementationInfos from the + // ContainerImplementationInfo + // to avoid too long syntax representation + const ::Deployment::ComponentImplementationInfos impl_infos = + container_impl_info.impl_infos; + + const CORBA::ULong len = impl_infos.length (); + retv->length (len); + + for (CORBA::ULong i = 0; i < len; ++i) + { + // Install home + Components::CCMHome_var home = + this->install_home (impl_infos[i] + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Components::KeylessCCMHome_var kh = + Components::KeylessCCMHome::_narrow (home.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (kh.in ())) + ACE_TRY_THROW (Deployment::InstallationFailure ()); + + // Create component from home + Components::CCMObject_var comp = + kh->create_component (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (comp.in ())) + ACE_TRY_THROW (Deployment::InstallationFailure ()); + + if (this->component_map_.bind + (impl_infos[i].component_instance_name.in (), + Components::CCMObject::_duplicate (comp.in ()))) + { + ACE_DEBUG ((LM_DEBUG, + "CIAO (%P|%t) Container_Impl.cpp -" + "CIAO::Container_Impl::install -" + "error in binding component " + "instance name [%s] into the component map \n", + impl_infos[i].component_instance_name.in ())); + ACE_TRY_THROW (Deployment::InstallationFailure ()); + } + + // Set the return value. + (*retv)[i].component_instance_name + = impl_infos[i].component_instance_name.in (); + + (*retv)[i].component_ref = + Components::CCMObject::_duplicate (comp.in ()); + + // Deal with Component instance related Properties. + // Now I am only concerning about the COMPOENTIOR and attribute + // configuration initialization. + + // I need to map Properties to Components::ConfigValues + ::Components::ConfigValues comp_attributes; + comp_attributes.length (0); + + const CORBA::ULong clen = impl_infos[i].component_config.length (); + for (CORBA::ULong prop_len = 0; prop_len < clen; ++prop_len) + { + // Set up the ComponentIOR attribute + if (ACE_OS::strcmp + (impl_infos[i].component_config[prop_len].name.in (), + "ComponentIOR") == 0) + { + const char * path; + impl_infos[i].component_config[prop_len].value >>= path; + + CORBA::String_var ior = + this->orb_->object_to_string (comp.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CIAO::Utility::write_IOR (path, ior.in ()) != 0) + { + if (CIAO::debug_level () > 1) + ACE_DEBUG ((LM_DEBUG, "Failed to write the IOR.\n")); + + ACE_TRY_THROW (CORBA::INTERNAL ()); + } + } + + // Set up the naming service attribute + if (ACE_OS::strcmp + (impl_infos[i].component_config[prop_len].name.in (), + "RegisterNaming") == 0) + { + const char * naming_context; + impl_infos[i]. + component_config[prop_len].value >>= naming_context; + + // Register the component with the naming service + ACE_DEBUG ((LM_DEBUG, + "Register component with naming service.\n")); + bool result = register_with_ns (naming_context, + this->orb_.in (), + comp.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (!result) + { + ACE_DEBUG ((LM_DEBUG, + "Failed to register with naming service.\n")); + } + + } + + // Initialize attributes through StandardConfigurator interface + // @@Todo: Currently I have to manually map + // the Deployment::Properties to + // Components::ConfigValues, we should use a + // common data structure in + // the future. - Gan + CORBA::ULong cur_len = comp_attributes.length (); + comp_attributes.length (cur_len + 1); + + Components::ConfigValue *item = new OBV_Components::ConfigValue (); + item->name (impl_infos[i].component_config[prop_len].name.in ()); + CORBA::Any tmp = impl_infos[i].component_config[prop_len].value; + item->value (tmp); + + comp_attributes[cur_len] = item; + } + + if (comp_attributes.length () != 0) + { + //std_configurator.set_configuration + ::Components::StandardConfigurator_var std_configurator = + comp->get_standard_configurator (); + + std_configurator->set_configuration (comp_attributes); + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Container_Impl::install\t\n"); + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + return retv._retn (); +} + +::Deployment::Properties * +CIAO::Container_Impl::properties (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ::Deployment::Properties *retval; + + ACE_NEW_THROW_EX (retval, + ::Deployment::Properties, + CORBA::INTERNAL ()); + ACE_CHECK_RETURN (0); + + *retval = this->properties_; + + return retval; +} + +::Deployment::NodeApplication_ptr +CIAO::Container_Impl::get_node_application (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + return ::Deployment::NodeApplication::_duplicate (this->nodeapp_.in ()); +} + +::Components::CCMHome_ptr +CIAO::Container_Impl::install_home ( + const ::Deployment::ComponentImplementationInfo & impl_info + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Deployment::UnknownImplId, + Deployment::ImplEntryPointNotFound, + Deployment::InstallationFailure, + Components::InvalidConfiguration)) +{ + if (CIAO::debug_level () > 9) + { + ACE_DEBUG ((LM_DEBUG, + "CIAO (%P|%t) Container_Impl.cpp -" + "CIAO::Container_Impl::install_home -" + "installing home for component " + "instance [%s] \n", + impl_info.component_instance_name.in ())); + } + + Components::CCMHome_var newhome = + this->container_->ciao_install_home (impl_info.executor_dll.in (), + impl_info.executor_entrypt.in (), + impl_info.servant_dll.in (), + impl_info.servant_entrypt.in (), + impl_info.component_instance_name.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Components::CCMHome::_nil ()); + + if (CIAO::debug_level () > 9) + { + ACE_DEBUG ((LM_DEBUG, + "CIAO (%P|%t) Container_Impl.cpp -" + "CIAO::Container_Impl::install_home -" + "success in installing home for component " + "instance [%s] \n", + impl_info.component_instance_name.in ())); + } + + // We don't have to do _narrow since the generated code makes sure of + // the object type for us + // Bind the home in the map. + if (this->home_map_.bind (impl_info.component_instance_name.in (), + Components::CCMHome::_duplicate (newhome.in ()))) + { + ACE_DEBUG ((LM_DEBUG, + "CIAO (%P|%t) Container_Impl.cpp -" + "CIAO::Container_Impl::install_home -" + "error in binding home for component " + "instance [%s] \n", + impl_info.component_instance_name.in ())); + ACE_THROW_RETURN (Deployment::InstallationFailure (), + Components::CCMHome::_nil ()); + } + + //Note: If the return value will be discarded, it must be kept in a var or + // release () will have to be called explicitly. + return newhome._retn (); +} + + +void +CIAO::Container_Impl::remove_home (const char * comp_ins_name + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Components::RemoveFailure)) +{ + Components::CCMHome_ptr home; + ACE_CString str (comp_ins_name); + + if (this->home_map_.find (str, home) != 0) + ACE_THROW (CORBA::BAD_PARAM ()); + + // @@TODO We should remove all components created by this home as well. + // This is not implemented yet. + + this->container_->ciao_uninstall_home (home + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // If the previous calls failed, what should we do here?? + CORBA::release (home); + + // @@ Still need to remove the home if the previous operation fails? + if (this->home_map_.unbind (str) == -1) + ACE_THROW (::Components::RemoveFailure ()); +} + +::Components::CCMHomes * +CIAO::Container_Impl::get_homes (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + Components::CCMHomes * tmp; + ACE_NEW_THROW_EX (tmp, + Components::CCMHomes (), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (0); + + Components::CCMHomes_var retval (tmp); + + const CORBA::ULong len = this->home_map_.current_size (); + retval->length (len); + + + CORBA::ULong i = 0; + const Home_Iterator end = this->home_map_.end (); + for (Home_Iterator iter (this->home_map_.begin ()); + iter != end; + ++iter, ++i) + { + retval[i] = Components::CCMHome::_duplicate ( (*iter).int_id_); + } + + return retval._retn (); +} + +// Remove all homes and components +void +CIAO::Container_Impl::remove (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Components::RemoveFailure)) +{ + // Remove all components first. + this->remove_components (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + // Even if above operation failed we should still remove homes. + const Home_Iterator end = this->home_map_.end (); + for (Home_Iterator iter (this->home_map_.begin ()); + iter != end; + ++iter) + { + this->container_->ciao_uninstall_home ( (*iter).int_id_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + CORBA::release ( (*iter).int_id_); + } + + this->home_map_.unbind_all (); + + //if (CIAO::debug_level () > 1) + if (true) + ACE_DEBUG ((LM_DEBUG, + "Removed all homes and components from this container!\n")); +} + +//////////////////////////////////////////////////////////////////////// +// Internal helper functions. +//////////////////////////////////////////////////////////////////////// + +void +CIAO::Container_Impl::remove_components (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Components::RemoveFailure)) +{ + // Remove all the components in the NodeApplication/Container + // Release all component servant object. + const Component_Iterator end = this->component_map_.end (); + for (Component_Iterator iter (this->component_map_.begin ()); + iter != end; + ++iter) + { + // Find the component home first, then call the remove_component + // on the home. + Components::CCMHome_ptr home; + if (this->home_map_.find ( (*iter).ext_id_, home) != 0) + ACE_THROW (CORBA::BAD_PARAM ()); + + // This will call ccm_passivate on the component executor. + home->remove_component (((*iter).int_id_).in ()); + ACE_CHECK; + + CORBA::release (((*iter).int_id_).in ()); + } + + this->component_map_.unbind_all (); + // To this point the servant should have been destroyed. However, + // if someone is still making calls on the servant, terrible thing + // will happen. +} + + +// Below method is not used actually. +void +CIAO::Container_Impl::remove_component (const char * comp_ins_name + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + Components::RemoveFailure)) +{ + Components::CCMObject_var comp; + Components::CCMHome_ptr home; + + ACE_CString str (comp_ins_name); + + /* Before we do remove component we have to inform the homeservant so + * Component::ccm_passivate () + * constainer::uninstall_component () ->deactivate_object () will be called. + * + * ccm_remove will be called when the poa destroys the servant. + */ + + if (this->component_map_.find (str, comp) != 0) + ACE_THROW (CORBA::BAD_PARAM ()); + + if (this->home_map_.find (str, home) != 0) + ACE_THROW (CORBA::BAD_PARAM ()); + + // This will call ccm_passivate on the component executor. + home->remove_component (comp.in ()); + ACE_CHECK; + + // If the previous calls failed, what should we do here?? + CORBA::release (comp.in ()); + + // @@ Still need to remove the home if the previous operation fails? + if (this->component_map_.unbind (str) == -1) + ACE_THROW (::Components::RemoveFailure ()); +} + +bool +CIAO::Container_Impl::register_with_ns (const char * obj_name, + CORBA::ORB_ptr orb, + Components::CCMObject_ptr obj + ACE_ENV_ARG_DECL) +{ + ACE_TRY + { + // Obtain the naming service + CORBA::Object_var naming_obj = + orb->resolve_initial_references ("NameService" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (naming_obj.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to get the Naming Service.\n"), + false); + + CosNaming::NamingContext_var naming_context = + CosNaming::NamingContext::_narrow (naming_obj.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Create a Naming Sequence + CosNaming::Name name (1); + name.length (1); + name[0].id = CORBA::string_dup (obj_name); + name[0].kind = CORBA::string_dup (""); + + // Register with the Name Server + naming_context->bind (name, obj ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + return true; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "CIAO (%P|%t) Container_Impl.cpp -" + "CIAO::Container_Impl::register_with_ns -" + "NodeApplication: failed to register " + "with naming service."); + return false; + } + ACE_ENDTRY; + return true; +} + +bool +CIAO::Container_Impl::unregister_with_ns (const char * obj_name, + CORBA::ORB_ptr orb + ACE_ENV_ARG_DECL) +{ + ACE_TRY + { + // Obtain the naming service + CORBA::Object_var naming_obj = + orb->resolve_initial_references ("NameService" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (naming_obj.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Unable to get the Naming Service.\n"), + false); + + CosNaming::NamingContext_var naming_context = + CosNaming::NamingContext::_narrow (naming_obj.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Create a Naming Sequence + CosNaming::Name name (1); + name.length (1); + name[0].id = CORBA::string_dup (obj_name); + name[0].kind = CORBA::string_dup (""); + + // Register with the Name Server + ACE_DEBUG ((LM_DEBUG, + "Unregister component with the name server : %s!\n", + obj_name)); + naming_context->unbind (name ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + return true; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "CIAO (%P|%t) Container_Impl.cpp -" + "CIAO::Container_Impl::unregister_with_ns -" + "NodeApplication: failed to unregister " + "with naming service."); + return false; + } + ACE_ENDTRY; + return true; +} + |