diff options
Diffstat (limited to 'TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp')
-rw-r--r-- | TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp b/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp new file mode 100644 index 00000000000..8d5c0cd2eee --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp @@ -0,0 +1,574 @@ +#include "Locator_Repository.h" +#include "Locator_XMLHandler.h" +#include "utils.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_ctype.h" +#include "ace/OS_NS_unistd.h" + +#include "ACEXML/parser/parser/Parser.h" +#include "ACEXML/common/FileCharStream.h" +#include "ACEXML/common/XML_Util.h" + +ACE_RCSID (ImplRepo_Service, Locator_Repository, "$Id$") + +static const char* STARTUP_COMMAND = "StartupCommand"; +static const char* WORKING_DIR = "WorkingDir"; +static const char* ENVIRONMENT = "Environment"; +static const char* ACTIVATION = "Activation"; +static const char* PARTIAL_IOR = "Location"; +static const char* IOR = "IOR"; +static const char* START_LIMIT = "StartLimit"; +static const char* ACTIVATOR = "Activator"; +static const char* SERVERS_ROOT_KEY = "Servers"; +static const char* ACTIVATORS_ROOT_KEY = "Activators"; +static const char* TOKEN = "Token"; + +#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_REGISTRY) +static const char* WIN32_REG_KEY = "Software\\TAO\\ImplementationRepository"; +#endif + +static ACE_CString lcase (const ACE_CString& s) +{ + ACE_CString ret(s); + for (size_t i = 0; i < ret.length (); ++i) + { + ret[i] = static_cast<char>(ACE_OS::ace_tolower (s[i])); + } + return ret; +} + +static void loadActivatorsAsBinary (ACE_Configuration& config, Locator_Repository::AIMap& map) +{ + ACE_Configuration_Section_Key root; + int err = config.open_section (config.root_section (), ACTIVATORS_ROOT_KEY, 0, root); + if (err == 0) + { + int index = 0; + ACE_CString name; + while (config.enumerate_sections (root, index, name) == 0) + { + ACE_CString ior; + u_int token; + + ACE_Configuration_Section_Key key; + + // Can't fail, because we're enumerating + config.open_section (root, name.c_str(), 0, key); + + config.get_string_value (key, IOR, ior); + config.get_integer_value (key, TOKEN, token); + + Activator_Info_Ptr info (new Activator_Info (name, token, ior)); + map.bind (lcase (name), info); + index++; + } + } +} + +static void loadServersAsBinary(ACE_Configuration& config, Locator_Repository::SIMap& map) +{ + ACE_Configuration_Section_Key root; + int err = config.open_section (config.root_section (), SERVERS_ROOT_KEY, 0, root); + if (err == 0) + { + int index = 0; + ACE_CString name; + while (config.enumerate_sections (root, index, name) == 0) + { + ACE_CString cmdline, dir, envstr, partial_ior, ior, aname; + u_int amodeint = ImplementationRepository::MANUAL; + u_int start_limit; + + ACE_Configuration_Section_Key key; + + // Can't fail, because we're enumerating + config.open_section (root, name.c_str (), 0, key); + + // Ignore any missing values. Server name is enough on its own. + config.get_string_value (key, ACTIVATOR, aname); + config.get_string_value (key, STARTUP_COMMAND, cmdline); + config.get_string_value (key, WORKING_DIR, dir); + config.get_string_value (key, ENVIRONMENT, envstr); + config.get_integer_value(key, ACTIVATION, amodeint); + config.get_string_value (key, PARTIAL_IOR, partial_ior); + config.get_string_value (key, IOR, ior); + config.get_integer_value(key, START_LIMIT, start_limit); + + ImplementationRepository::ActivationMode amode = + static_cast <ImplementationRepository::ActivationMode> (amodeint); + + ImplementationRepository::EnvironmentList env_vars = + ImR_Utils::parseEnvList (envstr); + + Server_Info_Ptr info (new Server_Info(name, aname, cmdline, + env_vars, dir, amode, start_limit, partial_ior, ior)); + map.bind (name, info); + index++; + } + } +} + +static void loadAsBinary (ACE_Configuration& config, Locator_Repository& repo) +{ + loadServersAsBinary (config, repo.servers ()); + loadActivatorsAsBinary (config, repo.activators ()); +} + +// Note : There is no saveAsBinary(), because the ACE_Configuration class +// supports saving of individual entries. + +static void convertEnvList (const Locator_XMLHandler::EnvList& in, ImplementationRepository::EnvironmentList& out) +{ + CORBA::ULong sz = in.size (); + out.length (sz); + for (CORBA::ULong i = 0; i < sz; ++i) + { + out[i].name = in[i].name.c_str (); + out[i].value = in[i].value.c_str (); + } +} + +class Server_Repo_XML_Callback : public Locator_XMLHandler::Callback +{ +public: + Server_Repo_XML_Callback(Locator_Repository& repo) + : repo_ (repo) + { + } + virtual void next_server (const ACE_CString& name, + const ACE_CString& aname, const ACE_CString& cmdline, + const Locator_XMLHandler::EnvList& envlst, const ACE_CString& dir, + const ACE_CString& amodestr, int start_limit, + const ACE_CString& partial_ior, const ACE_CString& ior) + { + ImplementationRepository::ActivationMode amode = + ImR_Utils::parseActivationMode (amodestr); + + ImplementationRepository::EnvironmentList env_vars; + convertEnvList (envlst, env_vars); + + int limit = start_limit < 1 ? 1 : start_limit; + + Server_Info_Ptr si (new Server_Info (name, aname, cmdline, + env_vars, dir, amode, limit, partial_ior, ior)); + + this->repo_.servers ().bind (name, si); + } + virtual void next_activator (const ACE_CString& aname, + long token, + const ACE_CString& ior) + { + Activator_Info_Ptr si (new Activator_Info (aname, token, ior)); + this->repo_.activators ().bind (lcase (aname), si); + } +private: + Locator_Repository& repo_; +}; + +static int loadAsXML (const ACE_CString& fname, Locator_Repository& repo) +{ + ACEXML_FileCharStream* fstm = new ACEXML_FileCharStream; // xml input source will take ownership + + if (fstm->open (fname.c_str()) != 0) + { + // This is not a real error. The xml file may not exist yet. + delete fstm; + return 0; + } + + Server_Repo_XML_Callback cb (repo); + + Locator_XMLHandler handler (cb); + + ACEXML_Parser parser; + + // InputSource takes ownership + ACEXML_InputSource input (fstm); + + parser.setContentHandler (&handler); + parser.setDTDHandler (&handler); + parser.setErrorHandler (&handler); + parser.setEntityResolver (&handler); + + ACEXML_TRY_NEW_ENV + { + parser.parse (&input ACEXML_ENV_ARG_PARAMETER); + ACEXML_TRY_CHECK; + } + ACEXML_CATCH (ACEXML_Exception, ex) + { + ACE_ERROR ((LM_ERROR, "Error during load of ImR persistence xml file.")); + ex.print (); + return -1; + } + ACEXML_ENDTRY; + return 0; +} + +// Note : Would pass servers by const&, but ACE hash map const_iterator is broken. +static void saveAsXML (const ACE_CString& fname, Locator_Repository& repo) +{ + FILE* fp = ACE_OS::fopen (fname.c_str (), "w"); + if (fp == 0) + { + ACE_ERROR ((LM_ERROR, "Couldn't write to file %s\n", fname.c_str())); + return; + } + ACE_OS::fprintf (fp,"<?xml version=\"1.0\"?>\n"); + ACE_OS::fprintf (fp,"<%s>\n", Locator_XMLHandler::ROOT_TAG); + + // Save servers + Locator_Repository::SIMap::ENTRY* sientry = 0; + Locator_Repository::SIMap::ITERATOR siit (repo.servers ()); + for (; siit.next (sientry); siit.advance() ) + { + Server_Info_Ptr& info = sientry->int_id_; + + ACE_CString name = ACEXML_escape_string (info->name); + ACE_CString activator = ACEXML_escape_string (info->activator); + ACE_CString cmdline = ACEXML_escape_string (info->cmdline); + ACE_CString wdir = ACEXML_escape_string (info->dir); + ACE_CString partial_ior = ACEXML_escape_string (info->partial_ior); + ACE_CString ior = ACEXML_escape_string (info->ior); + + ACE_OS::fprintf (fp,"\t<%s", Locator_XMLHandler::SERVER_INFO_TAG); + ACE_OS::fprintf (fp," name=\"%s\"", name.c_str ()); + ACE_OS::fprintf (fp," activator=\"%s\"", activator.c_str ()); + ACE_OS::fprintf (fp," command_line=\"%s\"", cmdline.c_str ()); + ACE_OS::fprintf (fp," working_dir=\"%s\"", wdir.c_str ()); + ACE_CString amodestr = ImR_Utils::activationModeToString (info->activation_mode); + ACE_OS::fprintf (fp," activation_mode=\"%s\"", amodestr.c_str ()); + ACE_OS::fprintf (fp," start_limit=\"%d\"", info->start_limit); + ACE_OS::fprintf (fp," partial_ior=\"%s\"", partial_ior.c_str ()); + ACE_OS::fprintf (fp," ior=\"%s\"", ior.c_str ()); + ACE_OS::fprintf (fp,">\n"); + + for (CORBA::ULong i = 0; i < info->env_vars.length (); ++i) + { + ACE_OS::fprintf (fp,"\t\t<%s", Locator_XMLHandler::ENVIRONMENT_TAG); + ACE_OS::fprintf (fp," name=\"%s\"", info->env_vars[i].name.in ()); + ACE_CString val = ACEXML_escape_string (info->env_vars[i].value.in ()); + ACE_OS::fprintf (fp," value=\"%s\"", val.c_str ()); + ACE_OS::fprintf (fp,"/>\n"); + } + + ACE_OS::fprintf (fp,"\t</%s>\n", Locator_XMLHandler::SERVER_INFO_TAG); + } + + // Save Activators + Locator_Repository::AIMap::ENTRY* aientry = 0; + Locator_Repository::AIMap::ITERATOR aiit (repo.activators ()); + for (; aiit.next (aientry); aiit.advance ()) + { + ACE_CString aname = aientry->ext_id_; + Activator_Info_Ptr& info = aientry->int_id_; + ACE_OS::fprintf (fp,"\t<%s", Locator_XMLHandler::ACTIVATOR_INFO_TAG); + ACE_OS::fprintf( fp," name=\"%s\"", aname.c_str ()); + ACE_OS::fprintf (fp," token=\"%d\"", info->token); + ACE_OS::fprintf (fp," ior=\"%s\"", info->ior.c_str ()); + ACE_OS::fprintf (fp,"/>\n"); + } + + ACE_OS::fprintf (fp,"</%s>\n", Locator_XMLHandler::ROOT_TAG); + ACE_OS::fclose (fp); +} + +Locator_Repository::Locator_Repository () +: rmode_ (Options::REPO_NONE) +, config_ (0) +{ +} + +int +Locator_Repository::init(const Options& opts) +{ + this->rmode_ = opts.repository_mode (); + this->fname_ = opts.persist_file_name (); + + int err = 0; + switch (this->rmode_) + { + case Options::REPO_NONE: + { + break; + } + case Options::REPO_HEAP_FILE: + { + if (opts.repository_erase ()) + { + ACE_OS::unlink ( this->fname_.c_str () ); + } + ACE_Configuration_Heap* heap = new ACE_Configuration_Heap (); + this->config_.reset (heap); + err = heap->open (this->fname_.c_str ()); + if (err == 0) + { + loadAsBinary (*this->config_, *this); + } + break; + } + case Options::REPO_REGISTRY: + { +#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_REGISTRY) + if (opts.repository_erase ()) + { + ACE_Configuration_Win32Registry config ( HKEY_LOCAL_MACHINE ); + ACE_Configuration_Section_Key root; + config.open_section (config.root_section(), "Software\\TAO", 0, root); + config.remove_section (root, "ImplementationRepository", 1); + } + HKEY root = ACE_Configuration_Win32Registry:: + resolve_key (HKEY_LOCAL_MACHINE, WIN32_REG_KEY); + this->config_.reset (new ACE_Configuration_Win32Registry( root)); + loadAsBinary (*this->config_, *this); +#else + ACE_ERROR ((LM_ERROR, "Registry persistence is only " + "supported on Windows\n")); + err = -1; +#endif + break; + } + case Options::REPO_XML_FILE: + { + if (opts.repository_erase ()) + { + ACE_OS::unlink ( this->fname_.c_str() ); + } + err = loadAsXML (this->fname_, *this); + break; + } + default: + { + bool invalid_rmode_specified = false; + ACE_ASSERT (invalid_rmode_specified); + ACE_UNUSED_ARG (invalid_rmode_specified); + err = -1; + } + } + return err; +} + +int +Locator_Repository::add_server (const ACE_CString& name, + const ACE_CString& aname, + const ACE_CString& startup_command, + const ImplementationRepository::EnvironmentList& env_vars, + const ACE_CString& working_dir, + ImplementationRepository::ActivationMode activation, + int start_limit, + const ACE_CString& partial_ior, + const ACE_CString& ior, + ImplementationRepository::ServerObject_ptr svrobj) +{ + int limit = start_limit < 1 ? 1 : start_limit; + Server_Info_Ptr info(new Server_Info (name, aname, startup_command, + env_vars, working_dir, activation, limit, partial_ior, ior, svrobj)); + + int err = servers ().bind (name, info); + if (err != 0) + { + return err; + } + this->update_server (*info); + return 0; +} + +int +Locator_Repository::add_activator (const ACE_CString& name, + const CORBA::Long token, + const ACE_CString& ior, + ImplementationRepository::Activator_ptr act) +{ + Activator_Info_Ptr info (new Activator_Info (name, token, ior, act)); + + int err = activators ().bind (lcase (name), info); + if (err != 0) + { + return err; + } + this->update_activator (*info); + return 0; +} + +int +Locator_Repository::update_server (const Server_Info& info) +{ + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT (this->config_.get () != 0); + + ACE_Configuration& cfg = *this->config_; + + ACE_Configuration_Section_Key root; + ACE_Configuration_Section_Key key; + int err = cfg.open_section (cfg.root_section(), SERVERS_ROOT_KEY, 1, root); + if (err != 0) + { + ACE_ERROR ((LM_ERROR, "Unable to open config section:%s\n", SERVERS_ROOT_KEY)); + return err; + } + err = cfg.open_section (root, info.name.c_str (), 1, key); + if (err != 0) + { + ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", info.name.c_str())); + return err; + } + + ACE_CString envstr = ImR_Utils::envListToString(info.env_vars); + + cfg.set_string_value (key, ACTIVATOR, info.activator.c_str ()); + cfg.set_string_value (key, STARTUP_COMMAND, info.cmdline.c_str ()); + cfg.set_string_value (key, WORKING_DIR, info.dir.c_str ()); + cfg.set_string_value (key, ENVIRONMENT, envstr); + cfg.set_integer_value (key, ACTIVATION, info.activation_mode); + cfg.set_integer_value (key, START_LIMIT, info.start_limit); + cfg.set_string_value (key, PARTIAL_IOR, info.partial_ior.c_str ()); + cfg.set_string_value (key, IOR, info.ior.c_str()); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML (this->fname_, *this); + } + return 0; +} + +int +Locator_Repository::update_activator (const Activator_Info& info) +{ + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT(this->config_.get () != 0); + + ACE_Configuration& cfg = *this->config_; + + ACE_Configuration_Section_Key root; + ACE_Configuration_Section_Key key; + int err = cfg.open_section (cfg.root_section(), ACTIVATORS_ROOT_KEY, 1, root); + if (err != 0) + { + ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", ACTIVATORS_ROOT_KEY)); + return err; + } + err = cfg.open_section (root, info.name.c_str (), 1, key); + if (err != 0) + { + ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", info.name.c_str())); + return err; + } + + cfg.set_integer_value (key, TOKEN, info.token); + cfg.set_string_value (key, IOR, info.ior.c_str ()); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML( this->fname_, *this); + } + return 0; +} + +Server_Info_Ptr +Locator_Repository::get_server (const ACE_CString& name) +{ + Server_Info_Ptr server (0); + servers ().find (name, server); + return server; +} + +Activator_Info_Ptr +Locator_Repository::get_activator (const ACE_CString& name) +{ + Activator_Info_Ptr activator (0); + activators ().find (lcase (name), activator); + return activator; +} + +bool +Locator_Repository::has_activator (const ACE_CString& name) +{ + Activator_Info_Ptr activator (0); + return activators().find (lcase (name), activator) == 0; +} + +int +Locator_Repository::remove_server (const ACE_CString& name) +{ + int ret = this->servers().unbind (name); + if (ret != 0) + { + return ret; + } + + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT (this->config_.get() != 0); + ACE_Configuration& cfg = *this->config_; + ACE_Configuration_Section_Key root; + int err = cfg.open_section (cfg.root_section (), SERVERS_ROOT_KEY, 0, root); + if (err != 0) + { + return 0; // Already gone. + } + ret = cfg.remove_section (root, name.c_str (), 1); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML (this->fname_, *this); + } + return ret; +} + +int +Locator_Repository::remove_activator (const ACE_CString& name) +{ + int ret = activators().unbind (lcase(name)); + if (ret != 0) + { + return ret; + } + + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT (this->config_.get () != 0); + ACE_Configuration& cfg = *this->config_; + ACE_Configuration_Section_Key root; + int err = cfg.open_section (cfg.root_section (), ACTIVATORS_ROOT_KEY, 0, root); + if (err != 0) + { + return 0; // Already gone. + } + ret = cfg.remove_section (root, name.c_str (), 1); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML (this->fname_, *this); + } + return ret; +} + +Locator_Repository::SIMap& +Locator_Repository::servers (void) +{ + return server_infos_; +} + +Locator_Repository::AIMap& +Locator_Repository::activators (void) +{ + return activator_infos_; +} + +const char* +Locator_Repository::repo_mode () +{ + switch (rmode_) + { + case Options::REPO_XML_FILE: + case Options::REPO_HEAP_FILE: + return fname_.c_str (); + case Options::REPO_REGISTRY: + return "Registry"; + case Options::REPO_NONE: + return "Disabled"; + } + return "Disabled"; +} |