00001
00002 #include "cafe/Config.hpp"
00003
00004 #include "TEnv.h"
00005 #include "TOrdCollection.h"
00006 #include "TObjArray.h"
00007 #include "TString.h"
00008 #include "TObjString.h"
00009 #include "THashList.h"
00010 #include "TDirectory.h"
00011 #include "TSystem.h"
00012
00013 #include <memory>
00014 #include <iostream>
00015 #include <set>
00016 #include <cstdlib>
00017 #include <cstring>
00018 #include <stdexcept>
00019
00020 namespace cafe {
00021
00023 std::set<std::string> Config::s_accessed;
00024
00025 Config::Config(const std::string& name)
00026 : _name(name)
00027 {}
00028
00029 Config::~Config()
00030 {}
00031
00032 std::string Config::replace(TEnv *env, const std::string& input)
00033 {
00034 using namespace std;
00035 string result(input);
00036
00037 string::size_type pos = result.find("%{");
00038 if(pos != string::npos) {
00039 string::size_type end = result.find('}', pos);
00040 if(end != string::npos && result.find('.', pos) < end) {
00041 string newkey = result.substr(pos + 2, end - pos - 2);
00042 s_accessed.insert(newkey);
00043 string newvalue = env->GetValue(newkey.c_str(), "");
00044 if (newvalue == "") {
00045 throw std::runtime_error("No value for " + newkey + " defined in the config files.");
00046 }
00047 result.replace(pos, end - pos + 1, newvalue);
00048
00049
00050 if ( newvalue.find(newkey) == string::npos ) {
00051 result = replace(env, result);
00052 }
00053 }
00054 pos = end;
00055 }
00056 return result;
00057 }
00058
00059 std::string Config::get(const std::string& key, const std::string& def)
00060 {
00061 return get(key, def.c_str());
00062 }
00063
00064
00065 std::string Config::get(const std::string& key, const char *def)
00066 {
00067 std::string full = _name + '.' + key;
00068 s_accessed.insert(full);
00069 return getEnv().GetValue(full.c_str(), def);
00070 }
00071
00072 int Config::get(const std::string& key, int def)
00073 {
00074 std::string full = _name + '.' + key;
00075 s_accessed.insert(full);
00076 return getEnv().GetValue(full.c_str(), def);
00077 }
00078
00079 double Config::get(const std::string& key, double def)
00080 {
00081 std::string full = _name + '.' + key;
00082 s_accessed.insert(full);
00083 return getEnv().GetValue(full.c_str(), def);
00084 }
00085
00086 bool Config::get(const std::string& key, bool def)
00087 {
00088 std::string full = _name + '.' + key;
00089 s_accessed.insert(full);
00090 return getEnv().GetValue(full.c_str(), def);
00091 }
00092
00093 std::vector<std::string> Config::getVString(const std::string& key, const std::string& delim)
00094 {
00095 s_accessed.insert(_name + '.' + key);
00096
00097 TString s(get(key, "").c_str());
00098 std::vector<std::string> result;
00099 TObjArray *tokens = s.Tokenize(delim.c_str());
00100 {
00101 TIter iter(tokens);
00102 while(TObject *p = iter.Next()) {
00103 TObjString *item = (TObjString*)p;
00104 result.push_back(item->GetString().Data());
00105 }
00106 }
00107 delete tokens;
00108 return result;
00109 }
00110
00111 std::vector<float> Config::getVFloat(const std::string& key, const std::string& delim)
00112 {
00113 s_accessed.insert(_name + '.' + key);
00114
00115 TString s(get(key, "").c_str());
00116 std::vector<float> result;
00117 TObjArray *tokens = s.Tokenize(delim.c_str());
00118 TIter iter(tokens);
00119 while(TObject *p = iter.Next()) {
00120 TObjString *item = (TObjString*)p;
00121 result.push_back(atof(item->GetString().Data()));
00122 }
00123 delete tokens;
00124 return result;
00125 }
00126
00127 std::vector<int> Config::getVInt(const std::string& key, const std::string& delim)
00128 {
00129 s_accessed.insert(_name + '.' + key);
00130
00131 TString s(get(key, "").c_str());
00132 std::vector<int> result;
00133 TObjArray *tokens = s.Tokenize(delim.c_str());
00134 TIter iter(tokens);
00135 while(TObject *p = iter.Next()) {
00136 TObjString *item = (TObjString*)p;
00137 result.push_back(strtol(item->GetString().Data(),0,0));
00138 }
00139 delete tokens;
00140 return result;
00141 }
00142
00143 void Config::set(const std::string& key, const std::string& value)
00144 {
00145 getEnv().SetValue(key.c_str(), value.c_str());
00146 }
00147
00148 void Config::dumpConfig(std::ostream& stream)
00149 {
00150 TIter next(getEnv().GetTable());
00151 TEnvRec *er;
00152 static const char *lc[] = { "Global", "User", "Local", "Changed" };
00153
00154 stream << "cafe::Config: Dumping configuration settings" << std::endl;
00155 while ((er = (TEnvRec*) next()))
00156 stream << Form("%-25s: %-30s [%s]",
00157 er->GetName(),er->GetValue(),lc[er->GetLevel()]) << std::endl;
00158 stream << "cafe::Config: End of configuration settings" << std::endl;
00159
00160 return;
00161 }
00162
00163 void Config::dumpConfig(TDirectory* const dir, std::string const name)
00164 {
00165 if (dir) {
00166 TObjArray array(getEnv().GetTable()->GetSize());
00167 array.SetOwner(kTRUE);
00168
00169 TIter next(getEnv().GetTable());
00170 TEnvRec *er;
00171 static const char *lc[] = { "Global", "User", "Local", "Changed" };
00172
00173 size_t index = 0;
00174 while ((er = (TEnvRec*) next())) {
00175 TObjString* str = new TObjString(Form("%-25s: %-30s [%s]",
00176 er->GetName(),
00177 er->GetValue(),
00178 lc[er->GetLevel()]));
00179 array[index] = str;
00180 ++index;
00181 }
00182
00183 dir->cd();
00184 array.Write(name.c_str(),TObject::kSingleKey);
00185
00186 }
00187
00188 return;
00189 }
00190
00191 namespace {
00192 std::auto_ptr<TEnv> _cleanup;
00193 }
00194
00195 TEnv& Config::getEnv()
00196 {
00197 static TEnv *_env;
00198
00199 if(_env == 0) {
00200
00201
00202
00203
00204
00205 if(const char *filename = gSystem->Getenv("CAFE_CONFIG")) {
00206 std::cout << "Reading configuration file: " << filename << std::endl;
00207
00208
00209
00210 _env = new TEnv("!@#$%^&");
00211 _env->ReadFile(filename, kEnvLocal);
00212 if(_env->GetTable()->GetSize() == 0) {
00213 delete _env;
00214 _env = 0;
00215 throw std::runtime_error(std::string("Config: specified configfile not found: ") + filename);
00216 }
00217 }
00218
00219 if(_env == 0) {
00220 _env = new TEnv("!@#$%^&");
00221 _env->ReadFile("./cafe.config", kEnvLocal);
00222 if(_env->GetTable()->GetSize() == 0) {
00223 delete _env;
00224 _env = 0;
00225 }
00226 }
00227
00228 if(_env == 0) {
00229 std::string ctx;
00230 if(const char *c = getenv("SRT_PRIVATE_CONTEXT")) {
00231 ctx += c;
00232 }
00233 ctx += "./cafe.config";
00234 _env = new TEnv("!@#$%^&");
00235 _env->ReadFile(ctx.c_str(), kEnvLocal);
00236 }
00237
00238
00239
00240
00241 std::set<std::string> _files_included;
00242
00243 bool add_more = false;
00244 do {
00245 add_more = false;
00246 TString s(_env->GetValue("cafe.Include", "")) ;
00247 std::auto_ptr<TObjArray> includes(s.Tokenize(" ,\t"));
00248 TIter iter(includes.get());
00249 while(TObject *p = iter.Next()) {
00250 std::string filename(((TObjString*)p)->GetString().Data());
00251 if(_files_included.count(filename) > 0) continue;
00252 if(gSystem->AccessPathName(filename.c_str(), kReadPermission)) {
00253 throw std::runtime_error("Include file does not exist: " + filename);
00254 }
00255 std::cout << "Including configuration file: " << filename << std::endl;
00256 _env->ReadFile((filename).c_str(), kEnvLocal);
00257 _files_included.insert(filename);
00258 add_more = true;
00259 }
00260 } while(add_more);
00261
00262 s_accessed.insert("cafe.Include");
00263 _cleanup = std::auto_ptr<TEnv>(_env);
00264
00265 }
00266 return *_env;
00267 }
00268
00269 void Config::resolve()
00270 {
00271 TEnv& env(getEnv());
00272 TIter next(env.GetTable());
00273 while(TEnvRec *rec = (TEnvRec *)next()) {
00274 const char *str = rec->GetValue();
00275 if(strstr(str, "%{")) {
00276 std::string new_value = replace(&env, str);
00277 env.SetValue(rec->GetName(), new_value.c_str());
00278 }
00279
00280 std::string st = rec->GetValue() ;
00281 if (st.rfind(" ") == st.size()-1) {
00282 std::string::size_type pos ;
00283 while((pos = st.rfind(" ")) == st.size()-1 && st.size() > 0)
00284 st.erase(pos) ;
00285 env.SetValue(rec->GetName(), st.c_str());
00286 }
00287 }
00288 }
00289
00290 std::vector<std::string> Config::checkConfiguration()
00291 {
00292 std::set<std::string> processors;
00293
00294
00295 for(std::set<std::string>::iterator it = s_accessed.begin();
00296 it != s_accessed.end();
00297 ++it) {
00298 std::string::size_type dot = (*it).find('.');
00299 if(dot != std::string::npos) {
00300 std::string processor_name = (*it).substr(0, dot);
00301 processors.insert(processor_name);
00302
00303 }
00304 }
00305
00306
00307 std::vector<std::string> result;
00308
00309 TIter next(getEnv().GetTable());
00310 while (TEnvRec *rec = (TEnvRec*) next()) {
00311 std::string name(rec->GetName());
00312 std::string::size_type dot = name.find('.');
00313 if(dot != std::string::npos) {
00314 if(processors.find(name.substr(0, dot)) != processors.end()) {
00315 if(s_accessed.find(name) == s_accessed.end()) {
00316 result.push_back(name);
00317 }
00318 }
00319 }
00320 }
00321
00322 return result;
00323 }
00324
00325
00326 std::vector<std::string> Config::variables(const std::string& name)
00327 {
00328
00329 std::vector<std::string> result;
00330
00331 TIter next(getEnv().GetTable());
00332 while (TEnvRec *rec = (TEnvRec*) next()) {
00333 std::string pname(rec->GetName());
00334 std::string::size_type dot = pname.find('.');
00335 if(dot != std::string::npos &&
00336 name ==pname.substr(0, dot))
00337 result.push_back(pname.substr(dot+1));
00338 }
00339 return result ;
00340 }
00341
00342 }
00343