00001 // 00002 // cfg_libconfig.cc - This subclass of the Config class for the consmgr 00003 // package uses the libconfig library, if available, to provide access 00004 // to configuration files of that format. More information on libconfig, 00005 // as well as sources to the libconfig library, can be found at: 00006 // http://www.hyperrealm.com/libconfig/ 00007 // 00008 // ***** BEGIN LICENSE BLOCK ***** 00009 // Version: MPL 1.1/GPL 2.0/LGPL 2.1 00010 // 00011 // The contents of this file are subject to the Mozilla Public License 00012 // Version 1.1 (the "License"); you may not use this file except in 00013 // compliance with the License. You may obtain a copy of the License at 00014 // http://www.mozilla.org/MPL/ 00015 // 00016 // Software distributed under the License is distributed on an "AS IS" 00017 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 00018 // the License for the specific language governing rights and limitations 00019 // under the License. 00020 // 00021 // The Original Code is the consmgr network/serial-line monitoring package. 00022 // 00023 // The Initial Developer of the Original Code is Chris P. Ross. 00024 // Portions created by the Initial Developer are Copyright (C) 2000-2008 00025 // the Initial Developer. All Rights Reserved. 00026 // 00027 // Contributor(s): 00028 // 00029 // Alternatively, the contents of this file may be used under the terms of 00030 // either the GNU General Public License Version 2 or later (the "GPL"), or 00031 // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 00032 // in which case the provisions of the GPL or the LGPL are applicable instead 00033 // of those above. If you wish to allow use of your version of this file only 00034 // under the terms of either the GPL or the LGPL, and not to allow others to 00035 // use your version of this file under the terms of the MPL, indicate your 00036 // decision by deleting the provisions above and replace them with the notice 00037 // and other provisions required by the GPL or the LGPL. If you do not delete 00038 // the provisions above, a recipient may use your version of this file under 00039 // the terms of any one of the MPL, the GPL or the LGPL. 00040 // 00041 // ***** END LICENSE BLOCK ***** 00042 00043 #if HAVE_LIBCONFIG 00044 00045 #include <sstream> 00046 00047 #include "cfg_libconfig.h" 00048 #include "consmgr.h" 00049 00050 // 00051 // Constructor & Destructor 00052 // 00053 00054 LibConfig::LibConfig(const string &filename) : Config(filename) 00055 { 00056 int pret; 00057 00058 // Instantiate the libconfig object mutex. 00059 pret = pthread_mutex_init(&mutex, NULL); 00060 PTHREAD_CHECK_AND_THROW(pret, "mutex_init(mutex)"); 00061 00062 // Lock the mutex, while we mess with the libconfig goo. 00063 pret = pthread_mutex_lock(&mutex); 00064 PTHREAD_CHECK_AND_THROW(pret, "mutex_lock(mutex)"); 00065 00066 try { 00067 config.readFile(filename.c_str()); 00068 // readFile can throw ParseException or FileIOException 00069 } catch (libconfig::ParseException &pe) { 00070 // Unlock the mutex, and return. 00071 pret = pthread_mutex_unlock(&mutex); 00072 throw (ConfigParseException(pe.getLine(), pe.getError())); 00073 } catch (libconfig::FileIOException &pe) { 00074 // Unlock the mutex, and return. 00075 pret = pthread_mutex_unlock(&mutex); 00076 // XXX - Perhaps we should have some sort of system-level subclass 00077 // of ConfigException for errors like this? 00078 throw (ConfigException("File I/O error reading libconfig configuration file " + filename)); 00079 } catch (...) { 00080 clog << "Got a non-libconfig exception, re-throwing" << endl; 00081 throw (ConfigException("Unknown exception parsing Libconfig config file")); 00082 } 00083 00084 // Unlock the mutex and return 00085 pret = pthread_mutex_unlock(&mutex); 00086 PTHREAD_CHECK_AND_THROW(pret, "mutex_unlock(mutex)"); 00087 00088 this->filename = filename; 00089 00090 return; 00091 } 00092 00093 LibConfig::~LibConfig(void) 00094 { 00095 int pret; 00096 00097 pret = pthread_mutex_destroy(&mutex); 00098 PTHREAD_CHECK_AND_THROW(pret, "mutex_destroy(mutex)"); 00099 00100 return; 00101 } 00102 00103 // 00104 // Methods 00105 // 00106 00107 void 00108 LibConfig::load_entry(const string &name) 00109 { 00110 int pret; 00111 00112 // Lock the mutex, while we mess with the libconfig goo. 00113 pret = pthread_mutex_lock(&mutex); 00114 PTHREAD_CHECK_AND_THROW(pret, "mutex_lock(mutex)"); 00115 00116 if (!config.exists(name)) 00117 throw ConfigUnfoundException(name); 00118 00119 // This should never throw an exception, right? Since exists was true? 00120 libconfig::Setting &entry = config.lookup(name); 00121 00122 // Okay, load any configuration matching the parameter keys we expect 00123 // from the entry into the std::map<>. 00124 for (std::vector<string>::const_iterator ki = Config::config_keys.begin() ; 00125 ki < Config::config_keys.end() ; ki++) { 00126 std::string key = *ki; 00127 std::string value; 00128 00129 if (entry.exists(key)) { 00130 // At the moment, we have no typing in the Config class. So, if 00131 // libconfig tells us it's a number, convert it to a string. 00132 if (entry[key].isNumber()) { 00133 std::ostringstream strval; 00134 00135 strval << (unsigned int)entry[key]; 00136 value = strval.str(); 00137 } else 00138 entry.lookupValue(key, value); 00139 00140 clog << "Loaded '" << key << "' (value '" << value << "') into the map" << endl; 00141 this->insert(std::pair<string,string>(key, value)); 00142 } 00143 // XXX - Warn about an unfound key? 00144 } 00145 00146 // And, we're done, so unlock the mutex 00147 pret = pthread_mutex_unlock(&mutex); 00148 PTHREAD_CHECK_AND_THROW(pret, "mutex_unlock(mutex)"); 00149 00150 return; 00151 } 00152 #endif /* HAVE_LIBCONFIG */