]> Creatis software - bbtk.git/blob - kernel/src/bbtkConfigurationFile.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkConfigurationFile.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkConfigurationFile.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/02/13 14:08:25 $
7   Version:   $Revision: 1.3 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See doc/license.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16
17 =========================================================================*/
18 /**
19  *\file
20  *\brief Class bbtk::ConfigurationFile
21  */
22
23 #include "bbtkConfigurationFile.h"
24 #include "bbtkMessageManager.h"
25 //#include "xmlParser.h"
26 #include <sys/stat.h> // for struct stat stFileInfo
27
28 #if defined(WIN32)
29 #include <direct.h> // for getcwd
30 #endif
31
32 namespace bbtk
33 {
34 /// Constructor
35 ConfigurationFile::ConfigurationFile()
36 {
37    char *execPath = GetExecutablePath();
38
39  #if defined(WIN32)
40    std::string slash("\\");
41  #else
42    std::string slash("/");
43  #endif
44  
45    // ==> Set system paths
46    mBin_path = execPath;
47    mInstall_path = mBin_path + slash + "..";
48    // The relative path to the doc folder (=BBTK_DOC_REL_PATH)
49    mDoc_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH);
50    // The path to the doc folder (=mInstall_path+"/"+mDoc_rel_path)
51    mDoc_path = mInstall_path + slash + mDoc_rel_path;
52    // The relative path to the doc folder (=BBTK_BBS_REL_PATH)
53    mBbs_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_BBS_REL_PATH);
54    // The path to the bbs folder (=mInstall_path+"/"+mBbs_rel_path)
55    mBbs_path = mInstall_path + slash + mBbs_rel_path;
56    // The relative path to the rsc folder (=BBTK_RSC_REL_PATH)
57    //   mRsc_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_RSC_REL_PATH);
58    // The path to the rsc folder (=mInstall_path+"/"+mRsc_rel_path)
59    //   mRsc_path = mInstall_path + slash + mRsc_rel_path;
60    // The path to the bbtk data folder 
61    // Initialized to mInstall_path+"/"+BBTK_DATA_REL_PATH
62    // But can be overriden by value read from bbtk_config.xml
63    mData_path = mInstall_path + slash + BBTK_STRINGIFY_SYMBOL(BBTK_DATA_REL_PATH);
64    //  MessageManager::SetMessageLevel("Config",1);
65    bbtkMessage("Config",1," ==> bin    : '"<<mBin_path<<"'"<<std::endl);
66    bbtkMessage("Config",1," ==> prefix : '"<<mInstall_path<<"'"<<std::endl);
67    bbtkMessage("Config",1," ==> doc    : '"<<mDoc_path<<"'"<<std::endl);
68    bbtkMessage("Config",1," ==> bbs    : '"<<mBbs_path<<"'"<<std::endl);
69    //   bbtkMessage("Config",1," ==> rsc    : '"<<mRsc_path<<"'"<<std::endl);
70    bbtkMessage("Config",1," ==> data   : '"<<mData_path<<"'"<<std::endl);
71
72    // ==> First we look for bbtk_config.xml in "."
73    char buf[2048];
74    const char *currentDir = getcwd(buf, 2048);
75      
76    if( !currentDir )
77    {
78       std::cerr << "Path was too long to fit on 2048 bytes ?!?" << std::endl;
79       // \todo : what else?
80       // How abort a constructor and warn the caller function?
81       // LG : throw an exception 
82    }
83
84    std::string configXmlFullPathName = currentDir + slash + "bbtk_config.xml";
85
86    if ( FileExists( configXmlFullPathName ))
87    {
88       bbtkMessage("Config",1, "ConfigurationFile : [" << configXmlFullPathName << 
89             "] found in current directory" << std::endl); 
90       //Read(configXmlFullPathName.c_str());
91       // traiter le fichier local     
92    }
93
94 // ==> Then we look for bbtk_config.xml in ".bbtk"
95    else 
96    {
97    #if defined(__GNUC__)
98       std::string str_home(getenv("HOME"));
99    #elif defined(_WIN32)
100       std::string str_home(getenv("USERPROFILE"));
101    #endif
102       configXmlFullPathName = str_home + slash + ".bbtk/bbtk_config.xml";
103       if (!FileExists( configXmlFullPathName ))
104       {         
105          // ==> Nothing found, we create bbtk_config.xml in ".bbtk"
106          InstallPath ();
107       }
108    }
109
110 // In any case, deal with bbtk_config.xml!
111    Read(configXmlFullPathName.c_str());
112 }
113
114 /// Destructor
115 ConfigurationFile::~ConfigurationFile()
116 {
117 }
118
119 // See : http://www.techbytes.ca/techbyte103.html for more O.S.
120 bool ConfigurationFile::FileExists(std::string strFilename) {
121   struct stat stFileInfo;
122   bool blnReturn;
123   int intStat;
124
125   // Attempt to get the file attributes
126   intStat = stat(strFilename.c_str(),&stFileInfo);
127   if(intStat == 0) {
128     // We were able to get the file attributes
129     // so the file obviously exists.
130     blnReturn = true;
131   } else {
132     // We were not able to get the file attributes.
133     // This may mean that we don't have permission to
134     // access the folder which contains this file. If you
135     // need to do that level of checking, lookup the
136     // return values of stat which will give you
137     // more details on why stat failed.
138     blnReturn = false;
139   }
140
141   return(blnReturn);
142 }
143
144
145 void ConfigurationFile::CreateConfigXML( char *rootDirectory )
146 {
147    FILE *fp;
148    char configXml[250];
149    sprintf (configXml , "%s/bbtk_config.xml", rootDirectory);
150    bbtkMessage("Config",1, "in CreateConfigXML[" << configXml << "]" << std::endl);
151    fp = fopen (configXml, "w");
152    fprintf(fp, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
153    //  fprintf(fp, "<!DOCTYPE config SYSTEM \"/mnt/windows/bbtk/bbtk_config.xml>\n");
154    fprintf(fp, "<config>\n");
155    fprintf(fp, "   <description>  </description>\n");
156    //   fprintf(fp, "   <url>  http://www.creatis.insa-lyon.fr/software/bbtk  </url>\n");
157    //  fprintf(fp, "   <install_path> </install_path>\n");
158    fprintf(fp, "   <bbs_path>     </bbs_path>\n");
159   // fprintf(fp, "   <ext_dll_path> </ext_dll_path>\n");
160    fprintf(fp, "   <package_path> </package_path>\n");
161    fprintf(fp, "   <data_path> </data_path>\n");//, BBTK_DATA_PATH);
162    /// \todo find a decent default value !
163    ///fprintf(fp, "   <default_temp_dir>  %s </default_temp_dir>\n", " ");
164    // when $ will be found, default_temp_dir value will be replaced
165    fprintf(fp, "   <default_temp_dir>$</default_temp_dir>\n");
166    fprintf(fp, "</config>\n");
167    fclose(fp);
168 }
169
170 char *ConfigurationFile::GetExecutablePath()
171 {
172     /// \todo : Think to delete it!
173     char *buf = (char *)malloc(512);
174     char *slash;
175
176 #if defined(WIN32)
177     GetModuleFileName(NULL, buf, 511);
178     slash = strrchr(buf, '\\');
179     if (slash)
180     {
181         *slash = 0;
182     }
183 #elif defined(__GNUC__)
184     int res;
185     res = readlink("/proc/self/exe", buf, 512);
186     if (res == -1)
187         return "";
188     buf[res] = 0;
189     slash = strrchr(buf, '/');
190     if (slash)
191     {
192         *slash = 0;
193     }
194 #else
195     return "";
196 #endif
197
198     return buf;
199 }
200
201
202
203 void ConfigurationFile::InstallPath ()
204 {
205
206 /*--------------------------------------------------
207 New policy for bbtk_config.xml :
208
209 if bbtk_config.xml found in current directory (user is an aware user!)
210    use it!
211    
212 else if bbtk_config.xml found in HOME/.bbtk (user already worked with it)
213    use it!
214    
215 else if bbtk_config.xml.tmp found in /usr/local/bin or c:\\Program Files\\BBTK\\bin
216    copy it as .bbtk/bbtk_config.xml
217    
218 else (nothing installed)
219    create a minimum version in HOME/.bbtk
220 ----------------------------------------------------*/
221
222
223 // -----------------------------------------------------------------
224 #if defined(__GNUC__)
225
226 // ------------------ create some usefull strings ----------------
227 // installed bbtk_path
228   char bbtk_path[100];
229   strcpy(bbtk_path, "/usr/local/bin");
230        
231 // rootDirectory
232   char rootDirectory[200];
233   sprintf( rootDirectory,  "%s/.bbtk", getenv("HOME"));
234       
235 // configPath
236   char configPath[200];
237   sprintf(configPath, "%s/bbtk_config.xml",rootDirectory);
238   
239 // makeDir
240   char makeDir[250];
241   sprintf( makeDir, "mkdir \"%s\" ", rootDirectory);
242
243 // configXmlTmp
244   char configXmlTmp[250]; 
245   sprintf(configXmlTmp, "%s/bbtk_config.xml.tmp", bbtk_path);
246
247 // copyFile
248   char copyFile[250];
249
250   if (!FileExists(configXmlTmp)) // bbtk_config.xml.tmp not found (not installed)
251   {  
252      if (!FileExists(rootDirectory)) // .bbtk not found
253      {
254        system(makeDir);  // create .bbtk
255      }
256
257      // if "bbtk_path/bbtk_config.xml.tmp" doesn't exist, hard-create a minimum version in .bbtk
258      CreateConfigXML( rootDirectory );// create .bbtk
259   }
260   else
261   {
262      sprintf(copyFile,"cp %s  %s/bbtk_config.xml ",configXmlTmp,rootDirectory );
263      if (!FileExists(rootDirectory))
264      {
265        //std::cout << "makeDir[" << makeDir << "]" << std::endl;
266        system(makeDir);
267      }
268
269      if (!FileExists(configPath))
270      {
271        system(copyFile);
272      }
273   }
274   return;
275    
276 // ------------------------------------------------------------------
277 #elif defined(WIN32)
278
279
280 // installed bbtk_path
281   char bbtk_path[100];
282   strcpy(bbtk_path, "\"c:\\Program Files\\BBTK\\bin\"");
283   char bbtk_path2[100];
284   strcpy(bbtk_path2, "c:\\Program Files\\BBTK\\bin");
285
286 // rootDirectory
287   char rootDirectory[200];  
288   sprintf(rootDirectory, "%s\\.bbtk",getenv("USERPROFILE"));
289   //  std::cout << "[" << rootDirectory << "]" << std::endl;
290     
291 // configPath
292   char configPath[200];
293   sprintf(configPath, "%s\\bbtk_config.xml",rootDirectory);
294     
295 // makeDir
296   char makeDir[250];
297   sprintf( makeDir, "mkdir \"%s\" ", rootDirectory);
298
299 // configXmlTmp
300   char configXmlTmp[250]; 
301   sprintf(configXmlTmp, "%s\\bbtk_config.xml.tmp", bbtk_path2);
302     
303 // copyFile
304   char copyFile[250];
305   
306   if (!FileExists(configXmlTmp)) // bbtk_config.xml.tmp not found
307   {
308      if (!FileExists(rootDirectory)) // .bbtk not found
309      {
310        system(makeDir);  // create .bbtk
311      }
312      
313      // if "bbtk_path/bbtk_config.xml.tmp" doesn't exist, hard-create a minimum version in .bbtk
314      CreateConfigXML( rootDirectory );// create .bbtk
315      return;
316   }  
317   
318   sprintf(copyFile,"copy %s\\bbtk_config.xml.tmp \"%s\"\\bbtk_config.xml ",bbtk_path,rootDirectory );
319     
320   int attribs = GetFileAttributes (rootDirectory);
321   bbtkMessage("Config",1,std::hex << attribs << " " << FILE_ATTRIBUTE_DIRECTORY << std::endl);
322   if ( attribs != 0xFFFFFFFF){
323     if ((attribs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY ) /// \TODO : check !
324     {
325       if ( GetFileAttributes( configPath ) == 0xFFFFFFFF)
326       {
327          system(copyFile);  
328       } 
329     }
330   } else {
331     system(makeDir);
332     system(copyFile); 
333   }    
334   return;  
335 // ------------------------------------------------------------------    
336 #else
337 /// \todo  ConfigurationFile::InstallPath() : exit when for not WIN32 and not__GNUC__
338
339   return;    
340 #endif
341
342 }
343
344 void ConfigurationFile::GetTextOrClear(const XMLNode& node, std::string& var)
345 {
346   if (node.nText()>0) 
347     {
348       var = node.getText();
349     }
350   else if (node.nClear()>0) 
351     {
352       var = node.getClear().lpszValue;
353     }
354   else 
355     {
356       std::string mess("Error : element <");
357       mess += node.getName();
358       mess += "> : no text nor <PRE></PRE> clear tag found";
359     }
360 }
361
362
363 // Gets the list of directories holding bb scripts, packages, dll, ... from the xml file
364 //      bbtk_config.xml
365
366 void ConfigurationFile::Read(const std::string& filename)
367 {
368
369   //std::cout << "=======================in  ConfigurationFile::Read filename [" <<filename << "]" << std::endl;
370   
371   mConfig_xml_full_path = filename;
372   XMLResults* res = new XMLResults;
373   XMLNode BB = XMLNode::parseFile((XMLCSTR)filename.c_str(),(XMLCSTR)"config",res);
374
375   if ( res->error != eXMLErrorNone ) 
376     {
377       std::ostringstream str;
378       str << XMLNode::getError(res->error);
379       str << " [line " << res->nLine << ", col "<<res->nColumn<<"] ";
380       str << " file "<<filename; 
381       delete res;
382       bbtkError(str.str());
383 //      throw ConfigurationException(str.str());
384     }
385   delete res;
386
387   int i,j;
388
389   // Description
390   for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"description"); i++) 
391     {
392       std::string val;
393       GetTextOrClear(BB.getChildNode((XMLCSTR)"description",&j),val);
394       mDescription += val;
395     }    
396
397   // Url
398   if( BB.nChildNode((XMLCSTR)"url") ) 
399      GetTextOrClear(BB.getChildNode((XMLCSTR)"url"),mUrl);
400
401   // Data_Path
402   if( BB.nChildNode((XMLCSTR)"data_path") ) 
403      GetTextOrClear(BB.getChildNode((XMLCSTR)"data_path"),mData_path);
404
405   // install_path
406   //  if( BB.nChildNode((XMLCSTR)"install_path") )
407   //   GetTextOrClear(BB.getChildNode((XMLCSTR)"install_path"),mInstall_path);
408
409   // always add "." (current working directory) at the begining
410   // bbs_paths
411   mBbs_paths.push_back("."); 
412   // add system bbs path 
413   mBbs_paths.push_back(mBbs_path);
414
415   for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"bbs_path"); i++) 
416     {
417       std::string val;
418       GetTextOrClear(BB.getChildNode((XMLCSTR)"bbs_path",&j),val);
419       mBbs_paths.push_back(val);
420     }
421
422   // package_paths
423   mPackage_paths.push_back(".");   
424   for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"package_path"); i++) 
425     {
426       std::string val;
427       GetTextOrClear(BB.getChildNode((XMLCSTR)"package_path",&j),val);
428       mPackage_paths.push_back(val);
429     }
430
431   // default_temp_dir
432   if( BB.nChildNode((XMLCSTR)"default_temp_dir") ) 
433      GetTextOrClear(BB.getChildNode((XMLCSTR)"default_temp_dir"),mDefault_temp_dir);
434
435   if ( mDefault_temp_dir == "$") // no value found in config_xml
436   {
437      size_t pos = mConfig_xml_full_path.find("bbtk_config.xml");
438      mDefault_temp_dir = mConfig_xml_full_path.substr (0,pos); 
439   }    
440   // file separator
441   #if defined(_WIN32)
442      mFile_separator = "\\";
443   #else
444      mFile_separator = "/";
445   #endif
446 }
447
448
449 } // namespace bbtk