00001 #include "Locator_Repository.h"
00002 #include "Locator_XMLHandler.h"
00003 #include "utils.h"
00004 #include "ace/OS_NS_stdio.h"
00005 #include "ace/OS_NS_ctype.h"
00006 #include "ace/OS_NS_unistd.h"
00007
00008 #include "ACEXML/parser/parser/Parser.h"
00009 #include "ACEXML/common/FileCharStream.h"
00010 #include "ACEXML/common/XML_Util.h"
00011
00012 ACE_RCSID (ImplRepo_Service, Locator_Repository, "Locator_Repository.cpp,v 1.11 2006/01/04 16:10:11 giovannd Exp")
00013
00014 static const char* STARTUP_COMMAND = "StartupCommand";
00015 static const char* WORKING_DIR = "WorkingDir";
00016 static const char* ENVIRONMENT = "Environment";
00017 static const char* ACTIVATION = "Activation";
00018 static const char* PARTIAL_IOR = "Location";
00019 static const char* IOR = "IOR";
00020 static const char* START_LIMIT = "StartLimit";
00021 static const char* ACTIVATOR = "Activator";
00022 static const char* SERVERS_ROOT_KEY = "Servers";
00023 static const char* ACTIVATORS_ROOT_KEY = "Activators";
00024 static const char* TOKEN = "Token";
00025
00026 #if defined (ACE_WIN32)
00027 static const char* WIN32_REG_KEY = "Software\\TAO\\ImplementationRepository";
00028 #endif
00029
00030 static ACE_CString lcase (const ACE_CString& s)
00031 {
00032 ACE_CString ret(s);
00033 for (size_t i = 0; i < ret.length (); ++i)
00034 {
00035 ret[i] = static_cast<char>(ACE_OS::ace_tolower (s[i]));
00036 }
00037 return ret;
00038 }
00039
00040 static void loadActivatorsAsBinary (ACE_Configuration& config, Locator_Repository::AIMap& map)
00041 {
00042 ACE_Configuration_Section_Key root;
00043 int err = config.open_section (config.root_section (), ACTIVATORS_ROOT_KEY, 0, root);
00044 if (err == 0)
00045 {
00046 int index = 0;
00047 ACE_CString name;
00048 while (config.enumerate_sections (root, index, name) == 0)
00049 {
00050 ACE_CString ior;
00051 u_int token;
00052
00053 ACE_Configuration_Section_Key key;
00054
00055
00056 config.open_section (root, name.c_str(), 0, key);
00057
00058 config.get_string_value (key, IOR, ior);
00059 config.get_integer_value (key, TOKEN, token);
00060
00061 Activator_Info_Ptr info (new Activator_Info (name, token, ior));
00062 map.bind (lcase (name), info);
00063 index++;
00064 }
00065 }
00066 }
00067
00068 static void loadServersAsBinary(ACE_Configuration& config, Locator_Repository::SIMap& map)
00069 {
00070 ACE_Configuration_Section_Key root;
00071 int err = config.open_section (config.root_section (), SERVERS_ROOT_KEY, 0, root);
00072 if (err == 0)
00073 {
00074 int index = 0;
00075 ACE_CString name;
00076 while (config.enumerate_sections (root, index, name) == 0)
00077 {
00078 ACE_CString cmdline, dir, envstr, partial_ior, ior, aname;
00079 u_int amodeint = ImplementationRepository::MANUAL;
00080 u_int start_limit;
00081
00082 ACE_Configuration_Section_Key key;
00083
00084
00085 config.open_section (root, name.c_str (), 0, key);
00086
00087
00088 config.get_string_value (key, ACTIVATOR, aname);
00089 config.get_string_value (key, STARTUP_COMMAND, cmdline);
00090 config.get_string_value (key, WORKING_DIR, dir);
00091 config.get_string_value (key, ENVIRONMENT, envstr);
00092 config.get_integer_value(key, ACTIVATION, amodeint);
00093 config.get_string_value (key, PARTIAL_IOR, partial_ior);
00094 config.get_string_value (key, IOR, ior);
00095 config.get_integer_value(key, START_LIMIT, start_limit);
00096
00097 ImplementationRepository::ActivationMode amode =
00098 static_cast <ImplementationRepository::ActivationMode> (amodeint);
00099
00100 ImplementationRepository::EnvironmentList env_vars =
00101 ImR_Utils::parseEnvList (envstr);
00102
00103 Server_Info_Ptr info (new Server_Info(name, aname, cmdline,
00104 env_vars, dir, amode, start_limit, partial_ior, ior));
00105 map.bind (name, info);
00106 index++;
00107 }
00108 }
00109 }
00110
00111 static void loadAsBinary (ACE_Configuration& config, Locator_Repository& repo)
00112 {
00113 loadServersAsBinary (config, repo.servers ());
00114 loadActivatorsAsBinary (config, repo.activators ());
00115 }
00116
00117
00118
00119
00120 static void convertEnvList (const Locator_XMLHandler::EnvList& in, ImplementationRepository::EnvironmentList& out)
00121 {
00122 CORBA::ULong sz = in.size ();
00123 out.length (sz);
00124 for (CORBA::ULong i = 0; i < sz; ++i)
00125 {
00126 out[i].name = in[i].name.c_str ();
00127 out[i].value = in[i].value.c_str ();
00128 }
00129 }
00130
00131 class Server_Repo_XML_Callback : public Locator_XMLHandler::Callback
00132 {
00133 public:
00134 Server_Repo_XML_Callback(Locator_Repository& repo)
00135 : repo_ (repo)
00136 {
00137 }
00138 virtual void next_server (const ACE_CString& name,
00139 const ACE_CString& aname, const ACE_CString& cmdline,
00140 const Locator_XMLHandler::EnvList& envlst, const ACE_CString& dir,
00141 const ACE_CString& amodestr, int start_limit,
00142 const ACE_CString& partial_ior, const ACE_CString& ior)
00143 {
00144 ImplementationRepository::ActivationMode amode =
00145 ImR_Utils::parseActivationMode (amodestr);
00146
00147 ImplementationRepository::EnvironmentList env_vars;
00148 convertEnvList (envlst, env_vars);
00149
00150 int limit = start_limit < 1 ? 1 : start_limit;
00151
00152 Server_Info_Ptr si (new Server_Info (name, aname, cmdline,
00153 env_vars, dir, amode, limit, partial_ior, ior));
00154
00155 this->repo_.servers ().bind (name, si);
00156 }
00157 virtual void next_activator (const ACE_CString& aname,
00158 long token,
00159 const ACE_CString& ior)
00160 {
00161 Activator_Info_Ptr si (new Activator_Info (aname, token, ior));
00162 this->repo_.activators ().bind (lcase (aname), si);
00163 }
00164 private:
00165 Locator_Repository& repo_;
00166 };
00167
00168 static int loadAsXML (const ACE_CString& fname, Locator_Repository& repo)
00169 {
00170 ACEXML_FileCharStream* fstm = new ACEXML_FileCharStream;
00171
00172 if (fstm->open (fname.c_str()) != 0)
00173 {
00174
00175 delete fstm;
00176 return 0;
00177 }
00178
00179 Server_Repo_XML_Callback cb (repo);
00180
00181 Locator_XMLHandler handler (cb);
00182
00183 ACEXML_Parser parser;
00184
00185
00186 ACEXML_InputSource input (fstm);
00187
00188 parser.setContentHandler (&handler);
00189 parser.setDTDHandler (&handler);
00190 parser.setErrorHandler (&handler);
00191 parser.setEntityResolver (&handler);
00192
00193 ACEXML_TRY_NEW_ENV
00194 {
00195 parser.parse (&input ACEXML_ENV_ARG_PARAMETER);
00196 ACEXML_TRY_CHECK;
00197 }
00198 ACEXML_CATCH (ACEXML_Exception, ex)
00199 {
00200 ACE_ERROR ((LM_ERROR, "Error during load of ImR persistence xml file."));
00201 ex.print ();
00202 return -1;
00203 }
00204 ACEXML_ENDTRY;
00205 return 0;
00206 }
00207
00208
00209 static void saveAsXML (const ACE_CString& fname, Locator_Repository& repo)
00210 {
00211 FILE* fp = ACE_OS::fopen (fname.c_str (), "w");
00212 if (fp == 0)
00213 {
00214 ACE_ERROR ((LM_ERROR, "Couldn't write to file %s\n", fname.c_str()));
00215 return;
00216 }
00217 ACE_OS::fprintf (fp,"<?xml version=\"1.0\"?>\n");
00218 ACE_OS::fprintf (fp,"<%s>\n", Locator_XMLHandler::ROOT_TAG);
00219
00220
00221 Locator_Repository::SIMap::ENTRY* sientry = 0;
00222 Locator_Repository::SIMap::ITERATOR siit (repo.servers ());
00223 for (; siit.next (sientry); siit.advance() )
00224 {
00225 Server_Info_Ptr& info = sientry->int_id_;
00226
00227 ACE_CString name = ACEXML_escape_string (info->name);
00228 ACE_CString activator = ACEXML_escape_string (info->activator);
00229 ACE_CString cmdline = ACEXML_escape_string (info->cmdline);
00230 ACE_CString wdir = ACEXML_escape_string (info->dir);
00231 ACE_CString partial_ior = ACEXML_escape_string (info->partial_ior);
00232 ACE_CString ior = ACEXML_escape_string (info->ior);
00233
00234 ACE_OS::fprintf (fp,"\t<%s", Locator_XMLHandler::SERVER_INFO_TAG);
00235 ACE_OS::fprintf (fp," name=\"%s\"", name.c_str ());
00236 ACE_OS::fprintf (fp," activator=\"%s\"", activator.c_str ());
00237 ACE_OS::fprintf (fp," command_line=\"%s\"", cmdline.c_str ());
00238 ACE_OS::fprintf (fp," working_dir=\"%s\"", wdir.c_str ());
00239 ACE_CString amodestr = ImR_Utils::activationModeToString (info->activation_mode);
00240 ACE_OS::fprintf (fp," activation_mode=\"%s\"", amodestr.c_str ());
00241 ACE_OS::fprintf (fp," start_limit=\"%d\"", info->start_limit);
00242 ACE_OS::fprintf (fp," partial_ior=\"%s\"", partial_ior.c_str ());
00243 ACE_OS::fprintf (fp," ior=\"%s\"", ior.c_str ());
00244 ACE_OS::fprintf (fp,">\n");
00245
00246 for (CORBA::ULong i = 0; i < info->env_vars.length (); ++i)
00247 {
00248 ACE_OS::fprintf (fp,"\t\t<%s", Locator_XMLHandler::ENVIRONMENT_TAG);
00249 ACE_OS::fprintf (fp," name=\"%s\"", info->env_vars[i].name.in ());
00250 ACE_CString val = ACEXML_escape_string (info->env_vars[i].value.in ());
00251 ACE_OS::fprintf (fp," value=\"%s\"", val.c_str ());
00252 ACE_OS::fprintf (fp,"/>\n");
00253 }
00254
00255 ACE_OS::fprintf (fp,"\t</%s>\n", Locator_XMLHandler::SERVER_INFO_TAG);
00256 }
00257
00258
00259 Locator_Repository::AIMap::ENTRY* aientry = 0;
00260 Locator_Repository::AIMap::ITERATOR aiit (repo.activators ());
00261 for (; aiit.next (aientry); aiit.advance ())
00262 {
00263 ACE_CString aname = aientry->ext_id_;
00264 Activator_Info_Ptr& info = aientry->int_id_;
00265 ACE_OS::fprintf (fp,"\t<%s", Locator_XMLHandler::ACTIVATOR_INFO_TAG);
00266 ACE_OS::fprintf( fp," name=\"%s\"", aname.c_str ());
00267 ACE_OS::fprintf (fp," token=\"%d\"", info->token);
00268 ACE_OS::fprintf (fp," ior=\"%s\"", info->ior.c_str ());
00269 ACE_OS::fprintf (fp,"/>\n");
00270 }
00271
00272 ACE_OS::fprintf (fp,"</%s>\n", Locator_XMLHandler::ROOT_TAG);
00273 ACE_OS::fclose (fp);
00274 }
00275
00276 Locator_Repository::Locator_Repository ()
00277 : rmode_ (Options::REPO_NONE)
00278 , config_ (0)
00279 {
00280 }
00281
00282 int
00283 Locator_Repository::init(const Options& opts)
00284 {
00285 this->rmode_ = opts.repository_mode ();
00286 this->fname_ = opts.persist_file_name ();
00287
00288 int err = 0;
00289 switch (this->rmode_)
00290 {
00291 case Options::REPO_NONE:
00292 {
00293 break;
00294 }
00295 case Options::REPO_HEAP_FILE:
00296 {
00297 if (opts.repository_erase ())
00298 {
00299 ACE_OS::unlink ( this->fname_.c_str () );
00300 }
00301 ACE_Configuration_Heap* heap = new ACE_Configuration_Heap ();
00302 this->config_.reset (heap);
00303 err = heap->open (this->fname_.c_str ());
00304 if (err == 0)
00305 {
00306 loadAsBinary (*this->config_, *this);
00307 }
00308 break;
00309 }
00310 case Options::REPO_REGISTRY:
00311 {
00312 #if defined (ACE_WIN32)
00313 if (opts.repository_erase ())
00314 {
00315 ACE_Configuration_Win32Registry config ( HKEY_LOCAL_MACHINE );
00316 ACE_Configuration_Section_Key root;
00317 config.open_section (config.root_section(), "Software\\TAO", 0, root);
00318 config.remove_section (root, "ImplementationRepository", 1);
00319 }
00320 HKEY root = ACE_Configuration_Win32Registry::
00321 resolve_key (HKEY_LOCAL_MACHINE, WIN32_REG_KEY);
00322 this->config_.reset (new ACE_Configuration_Win32Registry( root));
00323 loadAsBinary (*this->config_, *this);
00324 #else
00325 ACE_ERROR ((LM_ERROR, "Registry persistence is only "
00326 "supported on Windows\n"));
00327 err = -1;
00328 #endif
00329 break;
00330 }
00331 case Options::REPO_XML_FILE:
00332 {
00333 if (opts.repository_erase ())
00334 {
00335 ACE_OS::unlink ( this->fname_.c_str() );
00336 }
00337 err = loadAsXML (this->fname_, *this);
00338 break;
00339 }
00340 default:
00341 {
00342 bool invalid_rmode_specified = false;
00343 ACE_ASSERT (invalid_rmode_specified);
00344 ACE_UNUSED_ARG (invalid_rmode_specified);
00345 err = -1;
00346 }
00347 }
00348 return err;
00349 }
00350
00351 int
00352 Locator_Repository::add_server (const ACE_CString& name,
00353 const ACE_CString& aname,
00354 const ACE_CString& startup_command,
00355 const ImplementationRepository::EnvironmentList& env_vars,
00356 const ACE_CString& working_dir,
00357 ImplementationRepository::ActivationMode activation,
00358 int start_limit,
00359 const ACE_CString& partial_ior,
00360 const ACE_CString& ior,
00361 ImplementationRepository::ServerObject_ptr svrobj)
00362 {
00363 int limit = start_limit < 1 ? 1 : start_limit;
00364 Server_Info_Ptr info(new Server_Info (name, aname, startup_command,
00365 env_vars, working_dir, activation, limit, partial_ior, ior, svrobj));
00366
00367 int err = servers ().bind (name, info);
00368 if (err != 0)
00369 {
00370 return err;
00371 }
00372 this->update_server (*info);
00373 return 0;
00374 }
00375
00376 int
00377 Locator_Repository::add_activator (const ACE_CString& name,
00378 const CORBA::Long token,
00379 const ACE_CString& ior,
00380 ImplementationRepository::Activator_ptr act)
00381 {
00382 Activator_Info_Ptr info (new Activator_Info (name, token, ior, act));
00383
00384 int err = activators ().bind (lcase (name), info);
00385 if (err != 0)
00386 {
00387 return err;
00388 }
00389 this->update_activator (*info);
00390 return 0;
00391 }
00392
00393 int
00394 Locator_Repository::update_server (const Server_Info& info)
00395 {
00396 if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY)
00397 {
00398 ACE_ASSERT (this->config_.get () != 0);
00399
00400 ACE_Configuration& cfg = *this->config_;
00401
00402 ACE_Configuration_Section_Key root;
00403 ACE_Configuration_Section_Key key;
00404 int err = cfg.open_section (cfg.root_section(), SERVERS_ROOT_KEY, 1, root);
00405 if (err != 0)
00406 {
00407 ACE_ERROR ((LM_ERROR, "Unable to open config section:%s\n", SERVERS_ROOT_KEY));
00408 return err;
00409 }
00410 err = cfg.open_section (root, info.name.c_str (), 1, key);
00411 if (err != 0)
00412 {
00413 ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", info.name.c_str()));
00414 return err;
00415 }
00416
00417 ACE_CString envstr = ImR_Utils::envListToString(info.env_vars);
00418
00419 cfg.set_string_value (key, ACTIVATOR, info.activator.c_str ());
00420 cfg.set_string_value (key, STARTUP_COMMAND, info.cmdline.c_str ());
00421 cfg.set_string_value (key, WORKING_DIR, info.dir.c_str ());
00422 cfg.set_string_value (key, ENVIRONMENT, envstr);
00423 cfg.set_integer_value (key, ACTIVATION, info.activation_mode);
00424 cfg.set_integer_value (key, START_LIMIT, info.start_limit);
00425 cfg.set_string_value (key, PARTIAL_IOR, info.partial_ior.c_str ());
00426 cfg.set_string_value (key, IOR, info.ior.c_str());
00427 }
00428 else if (rmode_ == Options::REPO_XML_FILE)
00429 {
00430 saveAsXML (this->fname_, *this);
00431 }
00432 return 0;
00433 }
00434
00435 int
00436 Locator_Repository::update_activator (const Activator_Info& info)
00437 {
00438 if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY)
00439 {
00440 ACE_ASSERT(this->config_.get () != 0);
00441
00442 ACE_Configuration& cfg = *this->config_;
00443
00444 ACE_Configuration_Section_Key root;
00445 ACE_Configuration_Section_Key key;
00446 int err = cfg.open_section (cfg.root_section(), ACTIVATORS_ROOT_KEY, 1, root);
00447 if (err != 0)
00448 {
00449 ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", ACTIVATORS_ROOT_KEY));
00450 return err;
00451 }
00452 err = cfg.open_section (root, info.name.c_str (), 1, key);
00453 if (err != 0)
00454 {
00455 ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", info.name.c_str()));
00456 return err;
00457 }
00458
00459 cfg.set_integer_value (key, TOKEN, info.token);
00460 cfg.set_string_value (key, IOR, info.ior.c_str ());
00461 }
00462 else if (rmode_ == Options::REPO_XML_FILE)
00463 {
00464 saveAsXML( this->fname_, *this);
00465 }
00466 return 0;
00467 }
00468
00469 Server_Info_Ptr
00470 Locator_Repository::get_server (const ACE_CString& name)
00471 {
00472 Server_Info_Ptr server (0);
00473 servers ().find (name, server);
00474 return server;
00475 }
00476
00477 Activator_Info_Ptr
00478 Locator_Repository::get_activator (const ACE_CString& name)
00479 {
00480 Activator_Info_Ptr activator (0);
00481 activators ().find (lcase (name), activator);
00482 return activator;
00483 }
00484
00485 bool
00486 Locator_Repository::has_activator (const ACE_CString& name)
00487 {
00488 Activator_Info_Ptr activator (0);
00489 return activators().find (lcase (name), activator) == 0;
00490 }
00491
00492 int
00493 Locator_Repository::remove_server (const ACE_CString& name)
00494 {
00495 int ret = this->servers().unbind (name);
00496 if (ret != 0)
00497 {
00498 return ret;
00499 }
00500
00501 if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY)
00502 {
00503 ACE_ASSERT (this->config_.get() != 0);
00504 ACE_Configuration& cfg = *this->config_;
00505 ACE_Configuration_Section_Key root;
00506 int err = cfg.open_section (cfg.root_section (), SERVERS_ROOT_KEY, 0, root);
00507 if (err != 0)
00508 {
00509 return 0;
00510 }
00511 ret = cfg.remove_section (root, name.c_str (), 1);
00512 }
00513 else if (rmode_ == Options::REPO_XML_FILE)
00514 {
00515 saveAsXML (this->fname_, *this);
00516 }
00517 return ret;
00518 }
00519
00520 int
00521 Locator_Repository::remove_activator (const ACE_CString& name)
00522 {
00523 int ret = activators().unbind (lcase(name));
00524 if (ret != 0)
00525 {
00526 return ret;
00527 }
00528
00529 if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY)
00530 {
00531 ACE_ASSERT (this->config_.get () != 0);
00532 ACE_Configuration& cfg = *this->config_;
00533 ACE_Configuration_Section_Key root;
00534 int err = cfg.open_section (cfg.root_section (), ACTIVATORS_ROOT_KEY, 0, root);
00535 if (err != 0)
00536 {
00537 return 0;
00538 }
00539 ret = cfg.remove_section (root, name.c_str (), 1);
00540 }
00541 else if (rmode_ == Options::REPO_XML_FILE)
00542 {
00543 saveAsXML (this->fname_, *this);
00544 }
00545 return ret;
00546 }
00547
00548 Locator_Repository::SIMap&
00549 Locator_Repository::servers (void)
00550 {
00551 return server_infos_;
00552 }
00553
00554 Locator_Repository::AIMap&
00555 Locator_Repository::activators (void)
00556 {
00557 return activator_infos_;
00558 }
00559
00560 const char*
00561 Locator_Repository::repo_mode ()
00562 {
00563 switch (rmode_)
00564 {
00565 case Options::REPO_XML_FILE:
00566 case Options::REPO_HEAP_FILE:
00567 return fname_.c_str ();
00568 case Options::REPO_REGISTRY:
00569 return "Registry";
00570 case Options::REPO_NONE:
00571 return "Disabled";
00572 }
00573 return "Disabled";
00574 }