00001
00002
00003 #include "Iguana/Studio/interface/IgConfigElement.h"
00004 #include "Iguana/Framework/interface/IgArgsElement.h"
00005 #include "Iguana/Framework/interface/IgEnvsElement.h"
00006 #include <qfile.h>
00007 #include <qbuffer.h>
00008 #include <qdom.h>
00009 #include <fstream>
00010 #include <iostream>
00011 #include <sys/types.h>
00012 #include <unistd.h>
00013 #include <classlib/iobase/Filename.h>
00014 #include <classlib/iobase/File.h>
00015 #include <classlib/utils/UserInfo.h>
00016 #include <classlib/utils/DebugAids.h>
00017
00018
00019
00020
00021
00022
00023
00024
00025 IG_DEFINE_STATE_ELEMENT (IgConfigElement, "Services/Global/Config");
00026
00027
00028 class IgConfigElementNode {
00029 public:
00030
00031 IgConfigElementNode ()
00032 {hasValue = false;}
00033
00034 std::string name;
00035 std::string value;
00036 bool hasValue;
00037 std::vector<IgConfigElementNode> childs;
00038
00039 static IgConfigElementNode* find (IgConfigElementNode* node,
00040 const std::string& name);
00041 static void print (IgConfigElementNode* node,
00042 std::ostream& out,
00043 const std::string& itab = "");
00044 };
00045
00046
00047
00048
00049 IgConfigElement::IgConfigElement (IgState *state)
00050 : m_state (state),
00051 m_prefix (""),
00052 m_file (""),
00053 m_dirty (true)
00054 {
00055 ASSERT (m_state);
00056 m_state->put (s_key, this);
00057
00058 initConfiguration ();
00059 }
00060
00061 IgConfigElement::~IgConfigElement ()
00062 { m_state->detach (s_key); }
00063
00064 const IgConfigElement::KeyMap& IgConfigElement::getKeyMap () const
00065 { return m_config; }
00066
00067 void
00068 IgConfigElement::initConfiguration ()
00069 {
00070 IgArgsElement *args = IgArgsElement::get (m_state);
00071 ASSERT (args);
00072
00073 lat::UserInfo *user = lat::UserInfo::self ();
00074 if (args->find ("--ig-config", m_file, true))
00075 {
00076 lat::Filename f (m_file);
00077 if (f.isDirectory () || !f.isReadable ())
00078 {
00079 ASSERT ("ERROR: IGUANA configuration file does not exist or not a regular file" == 0);
00080 m_file = "";
00081 }
00082 }
00083 else
00084 {
00085 std::string home (user->homedir ());
00086 m_file = home + "/.iguana";
00087 lat::Filename dir (m_file);
00088 if(!dir.isDirectory ())
00089 dir.makedir (m_file, 0755, false, true);
00090 else if (!dir.isWritable () || !dir.isExecutable ())
00091 ASSERT ("ERROR: IGUANA configuration directory ~/.iguana is not writable. Please make sure that directory permission are 0755 and if it exists on an AFS area then you should have a valid AFS token." == 0);
00092
00093 m_file = m_file + "/iguana.conf";
00094 lat::Filename file (m_file);
00095 if (!file.exists ())
00096 {
00097 lat::File f;
00098 f.open (m_file, lat::IOFlags::OpenWrite | lat::IOFlags::OpenCreate);
00099 f.close();
00100 }
00101 }
00102 putValue ("/IgConfigElementInternal/PID", getpid ());
00103 putValue ("/IgConfigElementInternal/PPID", getppid ());
00104 putValue ("/IgConfigElementInternal/UID", user->uid ());
00105 putValue ("/IgConfigElementInternal/GID", user->uid ());
00106 putValue ("/IgConfigElementInternal/ID", user->id ());
00107 putValue ("/IgConfigElementInternal/USER", user->name ());
00108 putValue ("/IgConfigElementInternal/HOMEDIR", user->homedir ());
00109 putValue ("/IgConfigElementInternal/SHELL", user->shell ());
00110
00111 if (!m_file.empty ())
00112 {
00113 QDomDocument doc ("IGUANA_CONFIG");
00114 std::ifstream file;
00115 file.open (m_file.c_str ());
00116 ASSERT (file.good ());
00117
00118 QBuffer buffer;
00119 buffer.open (IO_ReadWrite);
00120 buffer.writeBlock ("<C>", 3);
00121
00122 char ch;
00123 file.get (ch);
00124 while (!file.eof ())
00125 {
00126 buffer.writeBlock (&ch, 1);
00127 file.get (ch);
00128 }
00129
00130 buffer.writeBlock ("</C>", 4);
00131 file.close ();
00132 buffer.reset ();
00133
00134 if (!doc.setContent (&buffer))
00135 ASSERT ("ERROR: Reading IGUANA configuration file" == 0);
00136 else
00137 processNode (doc.firstChild (), "");
00138 }
00139 m_dirty = false;
00140 }
00141
00142 void
00143 IgConfigElement::processNode (const QDomNode& node, const std::string& path)
00144 {
00145 if (node.isElement ())
00146 {
00147 if (node.nodeName () == "IgConfigElementInternal") return;
00148 std::string npath = path + "/" + node.nodeName ().latin1 ();
00149 if(node.hasChildNodes ())
00150 {
00151 QDomNode child = node.firstChild ();
00152 while (!child.isNull ())
00153 {
00154 processNode (child, npath);
00155 child = child.nextSibling ();
00156 }
00157 }
00158 else
00159 putValue (npath.substr (2), "", true);
00160 }
00161 else if (node.isText ())
00162 {
00163 std::string value (node.nodeValue ().latin1 ());
00164 std::string::iterator chr = value.begin ();
00165
00166 while (chr != value.end ())
00167 {
00168 if (*chr == '\n') value.erase (chr);
00169 else chr++;
00170 }
00171
00172 while (*value.begin () == ' ')
00173 value.erase (value.begin ());
00174
00175 while (*(--value.end ()) == ' ')
00176 value.erase (--value.end ());
00177
00178 putValue (path.substr (2), value, true);
00179 }
00180 }
00181
00182 void
00183 IgConfigElement::setPrefix (const std::string& prefix)
00184 {
00185 m_prefix = "/" + prefix;
00186 int index = -1;
00187 while ((index = m_prefix.find ("//")) != -1)
00188 m_prefix = m_prefix.replace (index, 2, "/");
00189 }
00190
00191 const std::string&
00192 IgConfigElement::prefix (void) const
00193 { return m_prefix; }
00194
00195 const std::string&
00196 IgConfigElement::substituteValue(std::string &value) const
00197 {
00198 IgEnvsElement* envs = IgEnvsElement::get (m_state);
00199 int spos = 0;
00200 while ((spos = value.rfind ("$", spos - 1)) != -1)
00201 {
00202 if (((int)value.size () > spos + 1) && (value[spos + 1] == '{'))
00203 {
00204 int epos = value.find ("}", spos);
00205 if (epos != -1)
00206 {
00207 std::string nval ("");
00208 if (epos > spos + 2)
00209 {
00210 std::string var (value.substr (spos + 2, epos - spos - 2));
00211 if (!getValue (var, nval) && !getValue ("/IgConfigElementInternal/" + var, nval))
00212 envs->getEnv (var, nval);
00213 }
00214 value = value.substr (0, spos) + nval + value.substr (epos + 1);
00215 }
00216 }
00217 if (spos == 0) break;
00218 }
00219 return value;
00220 }
00221
00222 bool
00223 IgConfigElement::getValue (const std::string& key, std::string& value) const
00224 {
00225 std::string fullkey = m_prefix + "/" + key;
00226 int sindex = -1;
00227 while ((sindex = fullkey.find ("//")) != -1)
00228 fullkey = fullkey.replace (sindex, 2, "/");
00229 std::map<std::string, std::string>::const_iterator itr =
00230 m_config.find (fullkey);
00231 if (itr != m_config.end ())
00232 {
00233 value = itr->second;
00234 substituteValue (value);
00235 return true;
00236 }
00237 return false;
00238 }
00239
00240 bool
00241 IgConfigElement::getValues (const std::string& key,
00242 std::vector<std::string>& values) const
00243 {
00244 std::string val;
00245 if (getValue (key, val))
00246 {
00247 std::string item ("");
00248 std::string separator (",");
00249 getValue ("separator", separator);
00250 size_t size = val.size ();
00251 for (size_t i = 0; i < size; i++)
00252 {
00253 if (val [i] == separator [0])
00254 {
00255 while (*item.begin () == ' ')
00256 item.erase (item.begin ());
00257 while (*(--item.end ()) == ' ')
00258 item.erase (--item.end ());
00259 values.push_back (item);
00260 item = "";
00261 }
00262 else
00263 item.push_back (val [i]);
00264 }
00265
00266 while (*item.begin () == ' ')
00267 item.erase (item.begin ());
00268 while (*(--item.end ()) == ' ')
00269 item.erase (--item.end ());
00270 values.push_back (item);
00271 return true;
00272 }
00273 return false;
00274 }
00275
00276 void
00277 IgConfigElement::putValue (const std::string& key,
00278 const std::string& value,
00279 bool override )
00280 {
00281 std::string fullkey = m_prefix + "/" + key;
00282 int sindex = -1;
00283 while ((sindex = fullkey.find ("//")) != -1)
00284 fullkey = fullkey.replace (sindex, 2, "/");
00285
00286 if (override || (m_config.find (fullkey) == m_config.end ()))
00287 {
00288 m_config [fullkey] = value;
00289 m_dirty = true;
00290 }
00291 }
00292
00293 void
00294 IgConfigElement::putValues (const std::string& key,
00295 const std::vector<std::string>& values,
00296 bool override )
00297 {
00298 std::string nvalue ("");
00299 if (values.size () > 0)
00300 {
00301 nvalue = values [0];
00302 std::string separator (",");
00303 getValue ("separator", separator);
00304 for (size_t i = 1; i < values.size (); i++)
00305 nvalue += separator + values [i];
00306 }
00307 putValue (key, nvalue, override);
00308 }
00309
00310 void
00311 IgConfigElement::convert (const std::string& str, bool& value) const
00312 {
00313 if (str.size () > 1)
00314 {
00315 if ((str == "true") || (str == "TRUE") || (str == "True"))
00316 value = true;
00317 else
00318 value = false;
00319 }
00320 else if ((str == "t") || (str == "T") || (str == "1"))
00321 value = true;
00322 else
00323 value = false;
00324 }
00325
00326 void
00327 IgConfigElement::save (const std::string& filename )
00328 {
00329 std::string file (filename);
00330 if (filename.empty ())
00331 file = m_file;
00332 if (!file.empty ())
00333 {
00334 if ((file == m_file) && !m_dirty) return;
00335 IgConfigElementNode head;
00336 head.name = "IgConfigElementHeadNodeDummy";
00337 std::map<std::string, std::string>::const_iterator itr =
00338 m_config.begin ();
00339 while (itr != m_config.end ())
00340 {
00341 if (itr->first.find ("/IgConfigElementInternal/") == 0)
00342 {
00343 itr++;
00344 continue;
00345 }
00346 IgConfigElementNode* cur = &head;
00347 std::string key = itr->first;
00348 std::string part ("");
00349 size_t size = key.size ();
00350 for (size_t i = 0; i < size; i++)
00351 {
00352 char ch = key [i];
00353 if (ch == '/')
00354 {
00355 if (part.empty ()) continue;
00356 cur = IgConfigElementNode::find (cur, part);
00357 part = "";
00358 }
00359 else
00360 part.push_back (ch);
00361 }
00362 if (!part.empty ())
00363 cur = IgConfigElementNode::find (cur, part);
00364 cur->value = itr->second;
00365 cur->hasValue = true;
00366 itr++;
00367 }
00368
00369 std::ofstream out;
00370 out.open (file.c_str ());
00371 ASSERT (out.good ());
00372 for (size_t i = 0; i < head.childs.size (); i++)
00373 IgConfigElementNode::print (&head.childs [i], out);
00374 out.close ();
00375 }
00376 }
00379
00380 IgConfigElementNode* IgConfigElementNode::find (IgConfigElementNode* node,
00381 const std::string& name)
00382 {
00383 if (node->name == "")
00384 node->name = name;
00385 else if (node->name == name)
00386 return node;
00387 else
00388 {
00389 for (size_t i = 0; i < node->childs.size (); i++)
00390 {
00391 if (node->childs [i].name == name)
00392 return &node->childs [i];
00393 }
00394 IgConfigElementNode child;
00395 child.name = name;
00396 node->childs.push_back (child);
00397 node = &node->childs [node->childs.size () - 1];
00398 }
00399 return node;
00400 }
00401
00402 void IgConfigElementNode::print (IgConfigElementNode* node,
00403 std::ostream& out,
00404 const std::string& itab )
00405 {
00406 if (node->name.empty()) return;
00407 out << itab.c_str () << "<" << node->name.c_str () << ">";
00408 if (node->hasValue)
00409 out << node->value.c_str () << "</" << node->name.c_str () << ">" << std::endl;
00410 else
00411 {
00412 out << std::endl;
00413 for (size_t i = 0; i < node->childs.size (); i++)
00414 print (&node->childs [i], out, itab + " ");
00415 out << itab.c_str () << "</" << node->name.c_str () << ">" << std::endl;
00416 }
00417 }
00418