application_config.cpp

Go to the documentation of this file.
00001 #ifndef APPLICATION_CONFIG_IMPLEMENTATION_FILE
00002 #define APPLICATION_CONFIG_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : application_config                                                *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 2000 By Author.  This program is free software; you can       *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "application_config.h"
00019 
00020 #include <basis/auto_synch.h>
00021 #include <basis/istring.h>
00022 #include <basis/log_base.h>
00023 #include <basis/mutex.h>
00024 #include <basis/set.cpp>
00025 #include <data_struct/section_manager.h>
00026 #include <data_struct/string_table.h>
00027 #include <opsystem/ini_config.h>
00028 #include <textual/parser_bits.h>
00029 #include <textual/tokenizer.h>
00030 
00031 //#define DEBUG_APP_CONFIG
00032   // uncomment for noisier debugging version.
00033 
00034 #undef LOG
00035 #define LOG(to_print) program_wide_logger().log(to_print)
00036 
00038 
00039 const char *PRODUCT_HEADING() { return "product"; }
00040   // the string used for our startup entries as a prefix to the product.
00041 
00042 const char *ASSIGN_TOKEN() { return "="; }
00043   // how we distinguish the key from the value for startup entries.
00044 
00045 const char *SEPARATOR_TOKEN() { return ","; }
00046   // the character between separate key/value pairs in the startup string.
00047 
00048 const char *SEPARATOR_TEXT() { return ", "; }
00049   // the string we use for the separator when printing it.
00050 
00051 const char *PARMS_HEADING() { return "parms"; }
00052   // the tag for parameters in the startup entry.
00053 
00054 const char *ONESHOT_HEADING() { return "oneshot"; }
00055   // the key name for startup entries' flag for once only execution.
00056 
00058 
00059 application_config::application_config(const istring &config_file,
00060     const istring &basename)
00061 : _lock(new mutex),
00062   _config(new ini_configurator(config_file, ini_configurator::RETURN_ONLY,
00063       ini_configurator::APPLICATION_DIRECTORY)),
00064   _sector(new section_manager(*_config, istring(basename) + "_TOC",
00065       istring(PRODUCT_HEADING()) + "_"))
00066 {
00067   FUNCDEF("constructor");
00068   string_table startup_info;
00069   if (!find_section(STARTUP_SECTION(), startup_info)) {
00070     // if there's no startup section, we do nothing right now.
00071     LOG("the startup section doesn't exist yet; adding it now.");
00072     istring entry = make_startup_entry(basename, "", false);
00073     startup_info.add(STARTUP_APP_NAME(), entry);
00074     add_section(STARTUP_SECTION(), startup_info);
00075   }
00076 }
00077 
00078 application_config::~application_config()
00079 {
00080   WHACK(_sector);
00081   WHACK(_config);
00082   WHACK(_lock);
00083 }
00084 
00085 const char *application_config::STARTUP_SECTION()
00086 { return "PRIVATE_STARTUP_LNCH1.0"; }
00087 
00088 const char *application_config::STARTUP_APP_NAME()
00089 { return "placeholder"; }
00090 
00091 bool application_config::product_exists(const istring &product)
00092 {
00093   auto_synchronizer l(*_lock);
00094   if (!_sector->section_exists(product)) return false;
00095   return true;
00096 }
00097 
00098 istring application_config::find_program(const istring &product,
00099     const istring &app_name, int &level)
00100 {
00101   auto_synchronizer l(*_lock);
00102   istring heading = _sector->make_section_heading(product);
00103   istring found = _sector->config().load(heading, app_name, "");
00105 //overly specific bits here...
00106 //hmmm: add this in as a specialization provided by real owner of class.
00107   if (!found) {
00108     // we didn't find the entry under the section we wanted to find it in.
00109     // there are a couple cases where we can kludge this section to a
00110     // different name, based on legacy requirements, and still find the
00111     // right item possibly.
00112     if (product.iequals("supervisor")) {
00113       // for some older installs, they say "supervisor" but mean "core".
00114       heading = _sector->make_section_heading("core");
00115       found = _sector->config().load(heading, app_name, "");
00116     } else if (product.iequals("lightlink")) {
00117       heading = _sector->make_section_heading("core");
00118       found = _sector->config().load(heading, app_name, "");
00119       if (!found) {
00120         // we can take one more remedial step for this phrase.
00121         heading = _sector->make_section_heading("server");
00122         found = _sector->config().load(heading, app_name, "");
00123       }
00124     }
00125   }
00126 //end of overly specific.
00128   found = parser_bits::substitute_env_vars(found);
00129 
00130   int comma_loc = found.find(",");
00131   if (negative(comma_loc)) return "";  // couldn't find our priority.
00132   level = found.convert(0);
00133   found.zap(0, comma_loc);
00134 
00135   return found;
00136 }
00137 
00138 bool application_config::add_program(const istring &product,
00139     const istring &app_name, const istring &full_path, int level)
00140 {
00141   FUNCDEF("add_program");
00142   auto_synchronizer l(*_lock);
00143   bool existed = true;
00144   // lookup the section, if it exists.
00145   string_table info_table;
00146   if (!_sector->section_exists(product)) {
00147     existed = false;
00148   } else
00149     find_section(product, info_table);
00150 #ifdef DEBUG_APP_CONFIG
00151   if (existed) {
00152     LOG(istring("section for ") + product + " found:");
00153     for (int i = 0; i < info_table.symbols(); i++)
00154       LOG(istring("key=") + info_table.name(i) + " value=" + info_table[i]);
00155   } else LOG(istring("section for ") + product + " not found.");
00156 #endif
00157   // remove any existing entry.
00158   info_table.whack(app_name);
00159   // plug in our new entry.
00160   isprintf full_entry("%d,%s", level, full_path.s());
00161   info_table.add(app_name, full_entry);
00162 #ifdef DEBUG_APP_CONFIG
00163   LOG(istring("new section for ") + product + " has:");
00164   for (int i = 0; i < info_table.symbols(); i++)
00165     LOG(istring("key=") + info_table.name(i) + " value=" + info_table[i]);
00166 #endif
00167   // now call the proper storage function based on whether the section
00168   // existed before or not.
00169   if (existed) return replace_section(product, info_table);
00170   else return add_section(product, info_table);
00171 }
00172 
00173 bool application_config::remove_program(const istring &product,
00174     const istring &app_name)
00175 {
00176   FUNCDEF("remove_program");
00177   auto_synchronizer l(*_lock);
00178   // if the section's missing, there's nothing to remove...
00179   string_table info_table;
00180   if (!find_section(product, info_table)) return true;
00181   // the section did exist, so remove any existing entry.
00182   info_table.whack(app_name);
00183   // now call the proper storage function based on whether the section
00184   // existed before or not.
00185   return replace_section(product, info_table);
00186 }
00187 
00188 bool application_config::find_section(const istring &section_name,
00189     string_table &info_found)
00190 {
00191   FUNCDEF("find_section");
00192   info_found.reset();
00193   auto_synchronizer l(*_lock);
00194   if (!_sector->find_section(section_name, info_found)) {
00195     LOG(section_name + " was not found in the configuration.");
00196     return false;
00197   }
00198   return true;
00199 }
00200 
00201 bool application_config::add_section(const istring &section_name,
00202     const string_table &info_found)
00203 {
00204   auto_synchronizer l(*_lock);
00205   return _sector->add_section(section_name, info_found);
00206 }
00207 
00208 bool application_config::replace_section(const istring &section_name,
00209     const string_table &info_found)
00210 {
00211   auto_synchronizer l(*_lock);
00212   return _sector->replace_section(section_name, info_found);
00213 }
00214 
00215 istring application_config::make_startup_entry(const istring &product,
00216     const istring &parms, bool one_shot)
00217 {
00218   return istring(PRODUCT_HEADING()) + ASSIGN_TOKEN() + product
00219       + SEPARATOR_TEXT() + PARMS_HEADING() + ASSIGN_TOKEN()
00220       + parms + SEPARATOR_TEXT() + ONESHOT_HEADING() + ASSIGN_TOKEN()
00221       + istring(istring::SPRINTF, "%d", one_shot);
00222 }
00223 
00224 bool application_config::parse_startup_entry(const istring &info,
00225     istring &product, istring &parms, bool &one_shot)
00226 {
00227   FUNCDEF("parse_startup_section");
00228   // parse the items that are in the entry for this program.
00229   tokenizer entry_parser(SEPARATOR_TOKEN(), ASSIGN_TOKEN());
00230   entry_parser.parse(info);
00231   // grab the pertinent bits for the program to be started.
00232   product = entry_parser.find(PRODUCT_HEADING());
00233   parms = entry_parser.find(PARMS_HEADING());
00234 //LOG(istring("parms=") + parms);
00235   istring once = entry_parser.find(ONESHOT_HEADING());
00236   one_shot = (bool)once.convert(0);
00237   // we require the product part at least.
00238   if (!product) return false;
00239   return true;
00240 }
00241 
00242 bool application_config::find_entry(const string_table &table,
00243     const istring &name, istring &location)
00244 {
00245   // seek the entry in the table specified.
00246   istring *found = table.find(name);
00247   if (!found) return false;
00248   // found the entry using the name.
00249   location = *found;
00250   return true;
00251 }
00252 
00253 bool application_config::add_startup_entry(const istring &product,
00254     const istring &app_name, const istring &parameters, int one_shot)
00255 {
00256   FUNCDEF("add_startup_entry");
00257   auto_synchronizer l(*_lock);
00258 
00259   LOG(istring("product \"") + product + "\", application \"" + app_name
00260       + (one_shot? istring("\", OneShot") : istring("\", MultiUse")));
00261 
00262   string_table startup_info;
00263   if (!find_section(STARTUP_SECTION(), startup_info)) {
00264     // if there's no startup section, we can't go on.  that should have been
00265     // created during startup of this program.
00266     LOG("internal startup section not found!");
00267     return false;
00268   }
00269 
00270   istring new_entry = make_startup_entry(product, parameters,
00271       one_shot);
00272   startup_info.add(app_name, new_entry);
00273   if (!replace_section(STARTUP_SECTION(), startup_info))
00274     return false;
00275 //hmmm: that's a bogus error; this is really an internal fup error.
00276 
00277   return true;
00278 }
00279 
00280 bool application_config::remove_startup_entry(const istring &product,
00281     const istring &app_name)
00282 {
00283   FUNCDEF("remove_startup_entry");
00284   auto_synchronizer l(*_lock);
00285 
00286   LOG(istring("product \"") + product + "\", application \"" + app_name + "\"");
00287 
00288   string_table startup_info;
00289   if (!find_section(STARTUP_SECTION(), startup_info)) {
00290     // if there's no startup section, we try to add one.
00291     add_section(STARTUP_SECTION(), startup_info);
00292     // if it still doesn't exist afterwards, we're hosed.
00293     if (!find_section(STARTUP_SECTION(), startup_info)) {
00295 //massive fup of some unanticipated sort.
00296 //complain.
00297       return false;
00298     }
00299   }
00300 
00301   // check that the entry already exists for this program.
00302   istring entry_found;
00303   if (!find_entry(startup_info, app_name, entry_found)) {
00304 //    COMPLAIN_APPLICATION;
00305     LOG(istring("no entry was found for ") + app_name);
00306     return false;
00307   }
00308 
00309   startup_info.whack(app_name);
00310   if (!replace_section(STARTUP_SECTION(), startup_info)) {
00311 //what happened with that?
00312     return false;
00313   }
00314 
00315   return true;
00316 }
00317 
00318 
00319 #endif //APPLICATION_CONFIG_IMPLEMENTATION_FILE
00320 

Generated on Wed Nov 19 04:28:55 2008 for HOOPLE Libraries by  doxygen 1.5.1