CMS 3D CMS Logo

IgConfigElement.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
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 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00019 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00020 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00021 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00022 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00023 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00024 
00025 IG_DEFINE_STATE_ELEMENT (IgConfigElement, "Services/Global/Config");
00026 
00027 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
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 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00047 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
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 /* = true*/)
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 /* = true*/)
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 

Generated on Tue Jun 9 17:38:49 2009 for CMSSW by  doxygen 1.5.4