]> 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/10/15 15:09:45 $
7   Version:   $Revision: 1.17 $
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 "bbtkXML.h"
26 #include "bbtkUtilities.h"
27
28 #if defined(WIN32)
29 #include <direct.h> // for getcwd
30 #endif
31
32
33
34 namespace bbtk
35 {
36
37   //====================================================================
38   /// Constructor
39   ConfigurationFile::ConfigurationFile()
40   {
41
42         mFile_separator = VALID_FILE_SEPARATOR;
43     
44     // ==> Set system paths 
45     mBin_path = GetExecutablePath();
46 //EED    mInstall_path = mBin_path + mFile_separator + "..";
47     mInstall_path = mBin_path + "/..";
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 //EED    mDoc_path = mInstall_path + mFile_separator + mDoc_rel_path;
52     mDoc_path = mInstall_path + "/" + mDoc_rel_path;
53     // The relative path to the doc folder (=BBTK_BBS_REL_PATH)
54     mBbs_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_BBS_REL_PATH);
55     // The path to the bbs folder (=mInstall_path+"/"+mBbs_rel_path)
56 //EED    mBbs_path = mInstall_path + mFile_separator + mBbs_rel_path;
57     mBbs_path = mInstall_path + "/" + mBbs_rel_path;
58     // The relative path to the rsc folder (=BBTK_RSC_REL_PATH)
59     //   mRsc_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_RSC_REL_PATH);
60     // The path to the rsc folder (=mInstall_path+"/"+mRsc_rel_path)
61     //   mRsc_path = mInstall_path + mFile_separator + mRsc_rel_path;
62     // The path to the bbtk data folder 
63     // Initialized to mInstall_path+"/"+BBTK_DATA_REL_PATH
64     // But can be overriden by value read from bbtk_config.xml
65 //EED    mData_path = mInstall_path + mFile_separator + BBTK_STRINGIFY_SYMBOL(BBTK_DATA_REL_PATH);
66     mData_path = mInstall_path + "/" + BBTK_STRINGIFY_SYMBOL(BBTK_DATA_REL_PATH);
67
68         Utilities::replace( mBin_path           , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
69         Utilities::replace( mInstall_path       , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
70         Utilities::replace( mDoc_rel_path       , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
71         Utilities::replace( mDoc_path           , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
72         Utilities::replace( mBbs_path           , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
73         Utilities::replace( mData_path          , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
74
75     bbtkMessage("Config",1," ==> bin    : '"<<mBin_path<<"'"<<std::endl);
76     bbtkMessage("Config",1," ==> prefix : '"<<mInstall_path<<"'"<<std::endl);
77     bbtkMessage("Config",1," ==> doc    : '"<<mDoc_path<<"'"<<std::endl);
78     bbtkMessage("Config",1," ==> bbs    : '"<<mBbs_path<<"'"<<std::endl);
79     bbtkMessage("Config",1," ==> data   : '"<<mData_path<<"'"<<std::endl);
80
81
82
83     
84     // bbs_paths
85     // always add "." (current working directory) at the begining
86         mBbs_paths.push_back( "." ); 
87     // add system bbs path 
88     mBbs_paths.push_back(mBbs_path);
89     // add toolsbbtk/appli 
90 //EED    std::string toolsappli_rel_path(mFile_separator);
91     std::string toolsappli_rel_path("/");
92 //EED    toolsappli_rel_path +=  "toolsbbtk" + mFile_separator + "appli";
93     toolsappli_rel_path +=  "toolsbbtk/appli";
94     //
95     //-----------------------------------------------------------
96     // LG : REMOVE BUGGY PATH WITH include *:
97     // 
98     //    mBbs_paths.push_back(mBbs_path + toolsappli_rel_path);
99     //-----------------------------------------------------------
100     int iStrVec,sizeStrVec;
101     
102     sizeStrVec = mBbs_paths.size();
103     for (iStrVec=0;iStrVec<sizeStrVec;iStrVec++){
104       Utilities::replace( mBbs_paths[iStrVec] , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
105     }
106
107     
108     // always add "." (current working directory) at the begining
109     mPackage_paths.push_back(".");   
110     // add system bin path (for build tree / standalone folder install)
111     mPackage_paths.push_back(mBin_path);
112     // add system lib path (for install tree)
113 //EED    mPackage_paths.push_back(mInstall_path + mFile_separator + "lib");
114     mPackage_paths.push_back(mInstall_path + "/lib");
115 #ifdef WIN32
116     // add bin/Debug bin/Release paths (for build/install tree)
117 //EED    mPackage_paths.push_back(mBin_path + mFile_separator + "Debug");
118     mPackage_paths.push_back(mBin_path + "/Debug");
119 //EED    mPackage_paths.push_back(mBin_path + mFile_separator + "Release");
120     mPackage_paths.push_back(mBin_path + "/Release");
121 #endif
122
123         sizeStrVec = mPackage_paths.size();
124         for (iStrVec=0;iStrVec<sizeStrVec;iStrVec++){
125                 Utilities::replace( mPackage_paths[iStrVec] , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
126         }
127
128
129
130     GetHelp(2);
131    
132     // ==> First we look for bbtk_config.xml in "."
133     char buf[2048];
134     const char *currentDir = getcwd(buf, 2048);
135     
136     if( !currentDir )
137       {
138         std::cerr << "Path was too long to fit on 2048 bytes ?!?" << std::endl;
139         // \todo : what else?
140         // How abort a constructor and warn the caller function?
141         // LG : throw an exception 
142       }
143     
144 //    std::string configXmlFullPathName = currentDir + mFile_separator + "bbtk_config.xml";
145     std::string configXmlFullPathName = currentDir ;
146                 configXmlFullPathName += "/bbtk_config.xml";
147         Utilities::replace( configXmlFullPathName , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
148
149     if ( Utilities::FileExists( configXmlFullPathName ))
150       {
151         bbtkMessage("Config",1, "ConfigurationFile : [" << configXmlFullPathName << 
152                     "] found in current directory" << std::endl); 
153         //Read(configXmlFullPathName.c_str());
154         // traiter le fichier local     
155       }
156     
157     // ==> Then we look for bbtk_config.xml in ".bbtk"
158     else 
159       {
160         configXmlFullPathName = Utilities::MakeUserSettingsFullFileName("bbtk_config.xml");
161         if (!Utilities::FileExists( configXmlFullPathName ))
162           {         
163             // ==> Nothing found, we create bbtk_config.xml in ".bbtk"
164             InstallPath ();
165           }
166       }
167     
168     // In any case, deal with bbtk_config.xml!
169     Read(configXmlFullPathName.c_str());
170   }
171   //=========================================================================
172
173   //=========================================================================
174   /// Destructor
175   ConfigurationFile::~ConfigurationFile()
176   {
177   }
178   //=========================================================================
179   
180
181
182
183   //=========================================================================
184   void ConfigurationFile::CreateConfigXML( char *rootDirectory )
185   {
186     FILE *fp;
187     char configXml[250];
188     sprintf (configXml , "%s/bbtk_config.xml", rootDirectory);
189     bbtkMessage("Config",1, "in CreateConfigXML[" << configXml << "]" << std::endl);
190     fp = fopen (configXml, "w");
191     fprintf(fp, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
192     //  fprintf(fp, "<!DOCTYPE config SYSTEM \"/mnt/windows/bbtk/bbtk_config.xml>\n");
193     fprintf(fp, "<config>\n");
194     fprintf(fp, "   <description>  </description>\n");
195     //   fprintf(fp, "   <url>  http://www.creatis.insa-lyon.fr/software/bbtk  </url>\n");
196     //  fprintf(fp, "   <install_path> </install_path>\n");
197     fprintf(fp, "   <bbs_path>     </bbs_path>\n");
198     // fprintf(fp, "   <ext_dll_path> </ext_dll_path>\n");
199     fprintf(fp, "   <package_path> </package_path>\n");
200     fprintf(fp, "   <data_path> </data_path>\n");//, BBTK_DATA_PATH);
201     /// \todo find a decent default value !
202       ///fprintf(fp, "   <default_temp_dir>  %s </default_temp_dir>\n", " ");
203       // when $ will be found, default_temp_dir value will be replaced
204       fprintf(fp, "   <default_temp_dir>$</default_temp_dir>\n");
205       fprintf(fp, "</config>\n");
206       fclose(fp);
207   }
208   //=========================================================================  
209
210
211   //=========================================================================
212   std::string ConfigurationFile::GetExecutablePath()
213   {
214     /// \todo : Think to delete it!
215     char *buf = (char *)malloc(512);
216     char *slash;
217     
218 #if defined(WIN32)
219     GetModuleFileName(NULL, buf, 511);
220     slash = strrchr(buf, '\\');
221     if (slash)
222       {
223         *slash = 0;
224       }
225 #elif defined(__GNUC__)
226     int res;
227     res = readlink("/proc/self/exe", buf, 512);
228     if (res == -1)
229       return "";
230     buf[res] = 0;
231     slash = strrchr(buf, '/');
232     if (slash)
233       {
234         *slash = 0;
235       }
236 #else
237     return "";
238 #endif
239     std::string ret(buf);
240     free(buf);
241     return ret;
242   }
243   //=========================================================================
244
245
246   //=========================================================================
247   void ConfigurationFile::InstallPath ()
248   {
249     
250     /*--------------------------------------------------
251       New policy for bbtk_config.xml :
252       
253       if bbtk_config.xml found in current directory (user is an aware user!)
254       use it!
255       
256       else if bbtk_config.xml found in HOME/.bbtk (user already worked with it)
257       use it!
258       
259       else if bbtk_config.xml.tmp found in /usr/local/bin or c:\\Program Files\\BBTK\\bin
260       copy it as .bbtk/bbtk_config.xml
261       
262       else (nothing installed)
263       create a minimum version in HOME/.bbtk
264       ----------------------------------------------------*/
265     
266     
267     // -----------------------------------------------------------------
268 #if defined(__GNUC__)
269     
270     // ------------------ create some usefull strings ----------------
271     // installed bbtk_path
272     char bbtk_path[100];
273     strcpy(bbtk_path, "/usr/local/bin");
274     
275     // rootDirectory
276     char rootDirectory[200];
277     sprintf( rootDirectory,  "%s/.bbtk", getenv("HOME"));
278     
279     // configPath
280     char configPath[200];
281     sprintf(configPath, "%s/bbtk_config.xml",rootDirectory);
282     
283     // makeDir
284     char makeDir[250];
285     sprintf( makeDir, "mkdir \"%s\" ", rootDirectory);
286     
287     // configXmlTmp
288     char configXmlTmp[250]; 
289     sprintf(configXmlTmp, "%s/bbtk_config.xml.tmp", bbtk_path);
290     
291     // copyFile
292     char copyFile[250];
293     
294     if (!Utilities::FileExists(configXmlTmp)) // bbtk_config.xml.tmp not found (not installed)
295       {  
296         if (!Utilities::FileExists(rootDirectory)) // .bbtk not found
297           {
298             system(makeDir);  // create .bbtk
299           }
300         
301         // if "bbtk_path/bbtk_config.xml.tmp" doesn't exist, hard-create a minimum version in .bbtk
302         CreateConfigXML( rootDirectory );// create .bbtk
303       }
304     else
305       {
306         sprintf(copyFile,"cp %s  %s/bbtk_config.xml ",configXmlTmp,rootDirectory );
307         if (!Utilities::FileExists(rootDirectory))
308           {
309             //std::cout << "makeDir[" << makeDir << "]" << std::endl;
310             system(makeDir);
311           }
312         
313         if (!Utilities::FileExists(configPath))
314           {
315             system(copyFile);
316           }
317       }
318     return;
319     
320     // ------------------------------------------------------------------
321 #elif defined(WIN32)
322     
323     
324     // installed bbtk_path
325     char bbtk_path[100];
326     strcpy(bbtk_path, "\"c:\\Program Files\\BBTK\\bin\"");
327     char bbtk_path2[100];
328     strcpy(bbtk_path2, "c:\\Program Files\\BBTK\\bin");
329     
330     // rootDirectory
331     char rootDirectory[200];  
332     sprintf(rootDirectory, "%s\\.bbtk",getenv("USERPROFILE"));
333     //  std::cout << "[" << rootDirectory << "]" << std::endl;
334     
335     // configPath
336     char configPath[200];
337     sprintf(configPath, "%s\\bbtk_config.xml",rootDirectory);
338     
339     // makeDir
340     char makeDir[250];
341     sprintf( makeDir, "mkdir \"%s\" ", rootDirectory);
342     
343     // configXmlTmp
344     char configXmlTmp[250]; 
345     sprintf(configXmlTmp, "%s\\bbtk_config.xml.tmp", bbtk_path2);
346     
347     // copyFile
348     char copyFile[250];
349     
350     if (!Utilities::FileExists(configXmlTmp)) // bbtk_config.xml.tmp not found
351       {
352         if (!Utilities::FileExists(rootDirectory)) // .bbtk not found
353           {
354             system(makeDir);  // create .bbtk
355           }
356         
357         // if "bbtk_path/bbtk_config.xml.tmp" doesn't exist, hard-create a minimum version in .bbtk
358         CreateConfigXML( rootDirectory );// create .bbtk
359         return;
360       }  
361     
362     sprintf(copyFile,"copy %s\\bbtk_config.xml.tmp \"%s\"\\bbtk_config.xml ",bbtk_path,rootDirectory );
363     
364     int attribs = GetFileAttributes (rootDirectory);
365     bbtkMessage("Config",1,std::hex << attribs << " " << FILE_ATTRIBUTE_DIRECTORY << std::endl);
366     if ( attribs != 0xFFFFFFFF)
367       {
368         if ((attribs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY ) /// \TODO : check !
369           {
370             if ( GetFileAttributes( configPath ) == 0xFFFFFFFF)
371               {
372                 system(copyFile);  
373               } 
374           }
375       } 
376     else 
377       {
378         system(makeDir);
379         system(copyFile); 
380       }    
381     return;  
382     // ------------------------------------------------------------------    
383 #else
384 /// \todo  ConfigurationFile::InstallPath() : exit when for not WIN32 and not__GNUC__
385
386   return;    
387 #endif
388
389 }
390   //=========================================================================
391
392
393
394   //=========================================================================
395   // Gets the list of directories holding bb scripts, packages, dll, ... from the xml file
396   //      bbtk_config.xml
397   
398   void ConfigurationFile::Read(const std::string& filename)
399   {
400     
401     bbtkDebugMessage("Config",1,"ConfigurationFile::Read(" <<filename << ")" << std::endl);
402     
403     mConfig_xml_full_path = filename;
404     XMLResults* res = new XMLResults;
405     XMLNode BB = XMLNode::parseFile((XMLCSTR)filename.c_str(),(XMLCSTR)"config",res);
406     
407     if ( res->error != eXMLErrorNone ) 
408       {
409         std::string mess = GetErrorMessage(res,filename);
410         delete res;
411         bbtkDebugMessage("Config",1,mess<< std::endl);
412         bbtkError(mess);
413       }
414     delete res;
415     
416     bbtkDebugMessage("Config",1,"OK" << std::endl);
417   
418     int i,j;
419     
420     // Description
421     for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"description"); i++) 
422       {
423         std::string val;
424         GetTextOrClear(BB.getChildNode((XMLCSTR)"description",&j),val);
425         mDescription += val;
426       }    
427     
428     // Url
429     if( BB.nChildNode((XMLCSTR)"url") ) 
430       GetTextOrClear(BB.getChildNode((XMLCSTR)"url"),mUrl);
431     
432     // Data_Path
433     if( BB.nChildNode((XMLCSTR)"data_path") ) 
434       GetTextOrClear(BB.getChildNode((XMLCSTR)"data_path"),mData_path);
435     
436     // install_path
437     //  if( BB.nChildNode((XMLCSTR)"install_path") )
438     //   GetTextOrClear(BB.getChildNode((XMLCSTR)"install_path"),mInstall_path);
439     
440     // add user bbs paths
441     for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"bbs_path"); i++) 
442       {
443         std::string val;
444         GetTextOrClear(BB.getChildNode((XMLCSTR)"bbs_path",&j),val);
445         mBbs_paths.push_back(val);
446       }
447     
448     // package_paths
449     
450     // add user package path
451     for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"package_path"); i++) 
452       {
453         std::string val;
454         GetTextOrClear(BB.getChildNode((XMLCSTR)"package_path",&j),val);
455         mPackage_paths.push_back(val);
456       }
457     
458     // default_temp_dir
459     if( BB.nChildNode((XMLCSTR)"default_temp_dir") ) 
460       GetTextOrClear(BB.getChildNode((XMLCSTR)"default_temp_dir"),mDefault_temp_dir);
461     
462     if ( mDefault_temp_dir == "$") // no value found in config_xml
463       {
464         size_t pos = mConfig_xml_full_path.find("bbtk_config.xml");
465         mDefault_temp_dir = mConfig_xml_full_path.substr (0,pos); 
466       }    
467
468     GetHelp(2);
469   }
470   //=========================================================================
471   
472   //=========================================================================
473   bool ConfigurationFile::AddPackagePathsAndWrite( const std::string& path )
474   {
475     bbtkDebugMessageInc("Config",9,
476                         "ConfigurationFile::AddPackagePathsAndWrite("
477                         <<path<<")"<<std::endl);
478     
479      XMLResults* res = new XMLResults;
480     XMLNode BB = 
481       XMLNode::parseFile((XMLCSTR)Get_config_xml_full_path().c_str(),
482                          (XMLCSTR)"config",res);
483     
484     if ( res->error != eXMLErrorNone ) 
485       {
486         std::string mess = GetErrorMessage(res,Get_config_xml_full_path());
487         delete res;
488         bbtkDebugMessage("Config",1,mess<< std::endl);
489         bbtkError(mess);
490       }
491    delete res;
492
493 #ifdef _WIN32
494     std::string bbs_path = path + "/bbs";
495 #else
496     std::string bbs_path = path + "/share/bbtk/bbs" ;
497 #endif
498     XMLNode BBSPATH = BB.addChild((XMLCSTR)"bbs_path");
499     BBSPATH.addText((XMLCSTR)bbs_path.c_str());
500     Utilities::replace(bbs_path, INVALID_FILE_SEPARATOR, VALID_FILE_SEPARATOR);
501     mBbs_paths.push_back(bbs_path);
502  
503 #ifdef _WIN32
504     std::string pack_path = path + "/bin";
505 #else
506     std::string pack_path = path ;
507 #endif
508     XMLNode PACKPATH = BB.addChild((XMLCSTR)"package_path");
509     PACKPATH.addText((XMLCSTR)pack_path.c_str());
510     Utilities::replace(pack_path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
511     mPackage_paths.push_back(pack_path);
512
513 #ifdef _WIN32
514     pack_path = path + "/Debug";
515     PACKPATH = BB.addChild((XMLCSTR)"package_path");
516     PACKPATH.addText((XMLCSTR)pack_path.c_str());
517     Utilities::replace(pack_path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
518     mPackage_paths.push_back(pack_path);
519     pack_path = path + "/Release";
520     PACKPATH = BB.addChild((XMLCSTR)"package_path");
521     PACKPATH.addText((XMLCSTR)pack_path.c_str());
522     Utilities::replace(pack_path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
523     mPackage_paths.push_back(pack_path);
524 #endif
525
526
527     XMLError err = BB.writeToFile((XMLCSTR)Get_config_xml_full_path().c_str());
528     if ( err != eXMLErrorNone ) 
529       {
530         std::string mess = GetErrorMessage(res,Get_config_xml_full_path());
531         bbtkDebugMessage("Config",1,mess<< std::endl);
532         bbtkError(mess);
533       }
534
535     return true;
536   }
537   //=========================================================================
538
539   //=========================================================================
540   void ConfigurationFile::GetHelp(int level) const
541   {
542     bbtkDebugMessageInc("Config",9,"ConfigurationFile::GetHelp("<<level
543                         <<")"<<std::endl);
544     
545     const std::string config_xml_full_path      = Get_config_xml_full_path();    
546     const std::string description               = Get_description();
547     const std::string url                       = Get_doc_path();
548     const std::string data_path                 = Get_data_path();
549     const std::string default_temp_dir          = Get_default_temp_dir();    
550     const std::string file_separator            = Get_file_separator();    
551     const std::vector<std::string>bbs_paths     = Get_bbs_paths();
552     const std::vector<std::string>package_paths = Get_package_paths();
553     
554     bbtkMessage("Help",level, "============="   << std::endl);           
555     bbtkMessage("Help",level, "Configuration"   << std::endl);
556     bbtkMessage("Help",level, "============="   << std::endl);
557     bbtkMessage("Help",level, "bbtk_config.xml    : [" << config_xml_full_path  << "]" << std::endl); 
558     bbtkMessage("Help",level, "Documentation Path : [" << url             << "]" << std::endl);
559     bbtkMessage("Help",level, "Data Path          : [" << data_path       << "]" << std::endl);
560     bbtkMessage("Help",level, "Temp Directory     : [" << default_temp_dir << "]" << std::endl);
561     bbtkMessage("Help",level, "File Separator     : [" << file_separator  << "]" << std::endl);
562
563     std::vector<std::string>::const_iterator i;
564            
565     bbtkMessage("Help",level, "BBS Paths   " << std::endl);     
566     for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
567     {
568       bbtkMessage("Help",level,"--- ["<<*i<<"]"<<std::endl);
569     }    
570     
571     bbtkMessage("Help",level, "PACKAGE Paths : " << std::endl);     
572     for (i = package_paths.begin(); i!=package_paths.end(); ++i )
573     {
574       bbtkMessage("Help",level,"--- ["<<*i<<"]"<<std::endl);
575     }
576
577     bbtkDebugDecTab("Config",9);
578   }
579   //=========================================================================
580
581
582 } // namespace bbtk