#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) 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(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 (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,"\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\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,"\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) 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"; }