]> Creatis software - bbtk.git/blob - kernel/src/bbtkConfigurationFile.cxx
MacOSX build
[bbtk.git] / kernel / src / bbtkConfigurationFile.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkConfigurationFile.cxx,v $
4   Language:  C++
5   Date:      $Date: 2008/11/12 12:47:00 $
6   Version:   $Revision: 1.21 $
7 =========================================================================*/
8
9 /* ---------------------------------------------------------------------
10
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
13 *
14 *  This software is governed by the CeCILL-B license under French law and 
15 *  abiding by the rules of distribution of free software. You can  use, 
16 *  modify and/ or redistribute the software under the terms of the CeCILL-B 
17 *  license as circulated by CEA, CNRS and INRIA at the following URL 
18 *  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
19 *  or in the file LICENSE.txt.
20 *
21 *  As a counterpart to the access to the source code and  rights to copy,
22 *  modify and redistribute granted by the license, users are provided only
23 *  with a limited warranty  and the software's author,  the holder of the
24 *  economic rights,  and the successive licensors  have only  limited
25 *  liability. 
26 *
27 *  The fact that you are presently reading this means that you have had
28 *  knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */                                                                         
30
31 /**
32  *\file
33  *\brief Class bbtk::ConfigurationFile
34  */
35
36 #include "bbtkConfigurationFile.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkXML.h"
39 #include "bbtkUtilities.h"
40
41 #if defined(WIN32)
42 # include <direct.h> // for getcwd
43 # include <windows.h>
44 #endif
45
46 #if defined(MACOSX) // assume this is OSX 
47 # include <sys/param.h>
48 # include <mach-o/dyld.h> // _NSGetExecutablePath : must add -framework CoreFoundation to link line 
49 # include <string.h>
50 # ifndef PATH_MAX
51 #  define PATH_MAX MAXPATHLEN
52 # endif
53 #endif // MACOSX
54
55 #ifndef PATH_MAX // If not defined yet : do it 
56 #  define PATH_MAX 2048
57 #endif
58
59
60 namespace bbtk
61 {
62
63   //====================================================================
64   /// Constructor
65   ConfigurationFile::ConfigurationFile()
66   {
67
68         mFile_separator = VALID_FILE_SEPARATOR;
69     
70     // ==> Set system paths 
71     mBin_path = GetExecutablePath();
72 //EED    mInstall_path = mBin_path + mFile_separator + "..";
73 #ifdef MACOSX
74           mInstall_path = mBin_path + "/../../../..";
75 #else
76           mInstall_path = mBin_path + "/..";
77 #endif
78           // The relative path to the doc folder (=BBTK_DOC_REL_PATH)
79     mDoc_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_DOC_REL_PATH);
80     // The path to the doc folder (=mInstall_path+"/"+mDoc_rel_path)
81 //EED    mDoc_path = mInstall_path + mFile_separator + mDoc_rel_path;
82     mDoc_path = mInstall_path + "/" + mDoc_rel_path;
83     // The relative path to the doc folder (=BBTK_BBS_REL_PATH)
84     mBbs_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_BBS_REL_PATH);
85     // The path to the bbs folder (=mInstall_path+"/"+mBbs_rel_path)
86 //EED    mBbs_path = mInstall_path + mFile_separator + mBbs_rel_path;
87     mBbs_path = mInstall_path + "/" + mBbs_rel_path;
88     // The relative path to the rsc folder (=BBTK_RSC_REL_PATH)
89     //   mRsc_rel_path = BBTK_STRINGIFY_SYMBOL(BBTK_RSC_REL_PATH);
90     // The path to the rsc folder (=mInstall_path+"/"+mRsc_rel_path)
91     //   mRsc_path = mInstall_path + mFile_separator + mRsc_rel_path;
92     // The path to the bbtk data folder 
93     // Initialized to mInstall_path+"/"+BBTK_DATA_REL_PATH
94     // But can be overriden by value read from bbtk_config.xml
95 //EED    mData_path = mInstall_path + mFile_separator + BBTK_STRINGIFY_SYMBOL(BBTK_DATA_REL_PATH);
96     mData_path = mInstall_path + "/" + BBTK_STRINGIFY_SYMBOL(BBTK_DATA_REL_PATH);
97
98         Utilities::replace( mBin_path           , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
99         Utilities::replace( mInstall_path       , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
100         Utilities::replace( mDoc_rel_path       , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
101         Utilities::replace( mDoc_path           , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
102         Utilities::replace( mBbs_path           , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
103         Utilities::replace( mData_path          , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
104
105     bbtkMessage("Config",1," ==> bin    : '"<<mBin_path<<"'"<<std::endl);
106     bbtkMessage("Config",1," ==> prefix : '"<<mInstall_path<<"'"<<std::endl);
107     bbtkMessage("Config",1," ==> doc    : '"<<mDoc_path<<"'"<<std::endl);
108     bbtkMessage("Config",1," ==> bbs    : '"<<mBbs_path<<"'"<<std::endl);
109     bbtkMessage("Config",1," ==> data   : '"<<mData_path<<"'"<<std::endl);
110
111
112
113     
114     // bbs_paths
115     // always add "." (current working directory) at the begining
116         mBbs_paths.push_back( "." ); 
117     // add system bbs path 
118     mBbs_paths.push_back(mBbs_path);
119     // add toolsbbtk/appli 
120 //EED    std::string toolsappli_rel_path(mFile_separator);
121     std::string toolsappli_rel_path("/");
122 //EED    toolsappli_rel_path +=  "toolsbbtk" + mFile_separator + "appli";
123     toolsappli_rel_path +=  "toolsbbtk/appli";
124     //
125     //-----------------------------------------------------------
126     // LG : REMOVE BUGGY PATH WITH include *:
127     // 
128     //    mBbs_paths.push_back(mBbs_path + toolsappli_rel_path);
129     //-----------------------------------------------------------
130     int iStrVec,sizeStrVec;
131     
132     sizeStrVec = mBbs_paths.size();
133     for (iStrVec=0;iStrVec<sizeStrVec;iStrVec++){
134       Utilities::replace( mBbs_paths[iStrVec] , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
135     }
136
137     
138     // always add "." (current working directory) at the begining
139     mPackage_paths.push_back(".");   
140     // add system bin path (for build tree / standalone folder install)
141     mPackage_paths.push_back(mBin_path);
142     // add system lib path (for install tree)
143 //EED    mPackage_paths.push_back(mInstall_path + mFile_separator + "lib");
144     mPackage_paths.push_back(mInstall_path + "/lib");
145 #ifdef WIN32
146     // add bin/Debug bin/Release paths (for build/install tree)
147 //EED    mPackage_paths.push_back(mBin_path + mFile_separator + "Debug");
148     mPackage_paths.push_back(mBin_path + "/Debug");
149 //EED    mPackage_paths.push_back(mBin_path + mFile_separator + "Release");
150     mPackage_paths.push_back(mBin_path + "/Release");
151 #endif
152
153         sizeStrVec = mPackage_paths.size();
154         for (iStrVec=0;iStrVec<sizeStrVec;iStrVec++){
155                 Utilities::replace( mPackage_paths[iStrVec] , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
156         }
157
158
159
160     GetHelp(2);
161    
162     // ==> First we look for bbtk_config.xml in "."
163     char buf[2048];
164     const char *currentDir = getcwd(buf, 2048);
165     
166     if( !currentDir )
167       {
168         std::cerr << "Path was too long to fit on 2048 bytes ?!?" << std::endl;
169         // \todo : what else?
170         // How abort a constructor and warn the caller function?
171         // LG : throw an exception 
172       }
173     
174 //    std::string configXmlFullPathName = currentDir + mFile_separator + "bbtk_config.xml";
175     std::string configXmlFullPathName = currentDir ;
176                 configXmlFullPathName += "/bbtk_config.xml";
177         Utilities::replace( configXmlFullPathName , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
178
179     if ( Utilities::FileExists( configXmlFullPathName ))
180       {
181         bbtkMessage("Config",1, "ConfigurationFile : [" << configXmlFullPathName << 
182                     "] found in current directory" << std::endl); 
183         //Read(configXmlFullPathName.c_str());
184         // traiter le fichier local     
185       }
186     
187     // ==> Then we look for bbtk_config.xml in ".bbtk"
188     else 
189       {
190         configXmlFullPathName = Utilities::MakeUserSettingsFullFileName("bbtk_config.xml");
191         if (!Utilities::FileExists( configXmlFullPathName ))
192           {         
193             // ==> Nothing found, we create bbtk_config.xml in ".bbtk"
194             InstallPath ();
195           }
196       }
197     
198     // In any case, deal with bbtk_config.xml!
199     Read(configXmlFullPathName.c_str());
200   }
201   //=========================================================================
202
203   //=========================================================================
204   /// Destructor
205   ConfigurationFile::~ConfigurationFile()
206   {
207   }
208   //=========================================================================
209   
210
211
212
213   //=========================================================================
214   void ConfigurationFile::CreateConfigXML( char *rootDirectory )
215   {
216     FILE *fp;
217     char configXml[250];
218     sprintf (configXml , "%s/bbtk_config.xml", rootDirectory);
219     bbtkDebugMessage("Config",1, "in CreateConfigXML[" << configXml << "]" << std::endl);
220     fp = fopen (configXml, "w");
221     fprintf(fp, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
222     fprintf(fp, "<config>\n");
223     fprintf(fp, "   <bbs_path>     </bbs_path>\n");
224     fprintf(fp, "   <package_path> </package_path>\n");
225     fprintf(fp, "   <default_temp_dir> $ </default_temp_dir>\n");    
226     fprintf(fp, "</config>\n");
227     fclose(fp);
228   }
229   //=========================================================================  
230
231         
232         
233         //=========================================================================  
234         // From http://www.fltk.org/newsgroups.php?gfltk.general+v:22083
235         //
236         int get_app_path (char *pname, size_t pathsize)
237         {
238 #ifdef LINUX
239         /* Oddly, the readlink(2) man page says no NULL is appended. */
240         /* So you have to do it yourself, based on the return value: */
241         pathsize --; /* Preserve a space to add the trailing NULL */
242         long result = readlink("/proc/self/exe", pname, pathsize);
243         if (result > 0)
244         {
245                         pname[result] = 0; /* add the #@!%ing NULL */
246                         
247                         if ((access(pname, 0) == 0))
248                                 return 0; /* file exists, return OK */
249                         /*else name doesn't seem to exist, return FAIL (falls
250                          through) */
251         }
252 #endif /* LINUX */
253                 
254 #ifdef WIN32
255         long result = GetModuleFileName(NULL, pname, pathsize);
256         if (result > 0)
257         {
258                         /* fix up the dir slashes... */
259                         int len = strlen(pname);
260                         int idx;
261                         for (idx = 0; idx < len; idx++)
262                         {
263                                 if (pname[idx] == '\\') pname[idx] = '/';
264                         }
265                         if ((access(pname, 0) == 0))
266                                 return 0; /* file exists, return OK */
267                         /*else name doesn't seem to exist, return FAIL (falls
268                          through) */
269         }
270 #endif /* WIN32 */
271                 
272 #ifdef SOLARIS
273         char *p = getexecname();
274         if (p)
275         {
276                         /* According to the Sun manpages, getexecname will
277                          "normally" return an */
278                         /* absolute path - BUT might not... AND that IF it is not,
279                          pre-pending */
280                         /* getcwd() will "usually" be the correct thing... Urgh!
281                          */
282                         
283                         /* check pathname is absolute (begins with a / ???) */
284                         if (p[0] == '/') /* assume this means we have an
285                          absolute path */
286                         {
287                                 strncpy(pname, p, pathsize);
288                                 if ((access(pname, 0) == 0))
289                                         return 0; /* file exists, return OK */
290                         }
291                         else /* if not, prepend getcwd() then check if file
292                          exists */
293                         {
294                                 getcwd(pname, pathsize);
295                                 long result = strlen(pname);
296                                 strncat(pname, "/", (pathsize - result));
297                                 result ++;
298                                 strncat(pname, p, (pathsize - result));
299                                 
300                                 if ((access(pname, 0) == 0))
301                                         return 0; /* file exists, return OK */
302                                 /*else name doesn't seem to exist, return FAIL
303                                  (falls through) */
304                         }
305         }
306 #endif /* SOLARIS */
307                 
308 #ifdef MACOSX /* assume this is OSX */
309                 /*
310                  from http://www.hmug.org/man/3/NSModule.html
311                  
312                  extern int _NSGetExecutablePath(char *buf, unsigned long
313                  *bufsize);
314                  
315                  _NSGetExecutablePath  copies  the  path  of the executable
316                  into the buffer and returns 0 if the path was successfully
317                  copied  in the provided buffer. If the buffer is not large
318                  enough, -1 is returned and the  expected  buffer  size  is
319                  copied  in  *bufsize.  Note that _NSGetExecutablePath will
320                  return "a path" to the executable not a "real path" to the
321                  executable.  That  is  the path may be a symbolic link and
322                  not the real file. And with  deep  directories  the  total
323                  bufsize needed could be more than MAXPATHLEN.
324                  */
325         int status = -1;
326         char *given_path = (char*)malloc(MAXPATHLEN * 2);
327         if (!given_path) return status;
328                 
329         uint32_t npathsize = MAXPATHLEN * 2;
330         long result = _NSGetExecutablePath(given_path, &npathsize);
331         if (result == 0)
332         { /* OK, we got something - now try and resolve the real path...
333                  */
334                         if (realpath(given_path, pname) != NULL)
335                         {
336                                 if ((access(pname, 0) == 0))
337                                         status = 0; /* file exists, return OK */
338                         }
339         }
340         free (given_path);
341         return status;
342 #endif /* MACOSX */
343                 
344         return -1; /* Path Lookup Failed */
345         } 
346         
347
348         
349   //=========================================================================
350   std::string ConfigurationFile::GetExecutablePath()
351   {
352           char name[PATH_MAX];
353           int err = get_app_path(name, PATH_MAX);
354           if (err) 
355           {
356                 bbtkError("Could not determine current executable path ?");  
357           }
358           
359           // remove the exe name
360           char *slash;          
361           slash = strrchr(name, VALID_FILE_SEPARATOR_CHAR);
362           if (slash)
363           {
364                   *slash = 0;
365           }
366           return name;
367   }
368           
369 /*        
370     /// \todo : Think to delete it!
371     char *buf = (char *)malloc(512);
372         if (!buf) 
373         {
374                 bbtkError("Could not allocate 512 bytes !");
375         }
376     char *slash;
377     
378 #if defined(WIN32)
379     GetModuleFileName(NULL, buf, 511);
380     slash = strrchr(buf, '\\');
381     if (slash)
382       {
383         *slash = 0;
384       }
385 #endif 
386           
387
388 #if defined(__GNUC__)
389     int res;
390     res = readlink("/proc/self/exe", buf, 512);
391     if (res == -1)
392         {
393             free(buf);
394                 
395         }
396     buf[res] = 0;
397     slash = strrchr(buf, '/');
398     if (slash)
399       {
400         *slash = 0;
401       }
402 #endif
403     std::string ret(buf);
404     free(buf);
405     return ret;
406   }
407   //=========================================================================
408 */
409
410   //=========================================================================
411   void ConfigurationFile::InstallPath ()
412   {
413     
414     /*--------------------------------------------------
415       New policy for bbtk_config.xml :
416       
417       if bbtk_config.xml found in current directory (user is an aware user!)
418       use it!
419       
420       else if bbtk_config.xml found in HOME/.bbtk (user already worked with it)
421       use it!
422       
423       else if bbtk_config.xml.tmp found in /usr/local/bin or c:\\Program Files\\BBTK\\bin
424       copy it as .bbtk/bbtk_config.xml
425       
426       else (nothing installed)
427       create a minimum version in HOME/.bbtk
428       ----------------------------------------------------*/
429     
430     
431     // -----------------------------------------------------------------
432 #if defined(__GNUC__)
433     
434     // ------------------ create some usefull strings ----------------
435     // installed bbtk_path
436     char bbtk_path[100];
437     strcpy(bbtk_path, "/usr/local/bin");
438     
439     // rootDirectory
440     char rootDirectory[200];
441     sprintf( rootDirectory,  "%s/.bbtk", getenv("HOME"));
442     
443     // configPath
444     char configPath[200];
445     sprintf(configPath, "%s/bbtk_config.xml",rootDirectory);
446     
447     // makeDir
448     char makeDir[250];
449     sprintf( makeDir, "mkdir \"%s\" ", rootDirectory);
450     
451     // configXmlTmp
452     char configXmlTmp[250]; 
453     sprintf(configXmlTmp, "%s/bbtk_config.xml.tmp", bbtk_path);
454     
455     // copyFile
456     char copyFile[250];
457     
458     if (!Utilities::FileExists(configXmlTmp)) // bbtk_config.xml.tmp not found (not installed)
459       {  
460         if (!Utilities::FileExists(rootDirectory)) // .bbtk not found
461           {
462             system(makeDir);  // create .bbtk
463           }
464         
465         // if "bbtk_path/bbtk_config.xml.tmp" doesn't exist, hard-create a minimum version in .bbtk
466         CreateConfigXML( rootDirectory );// create .bbtk
467       }
468     else
469       {
470         sprintf(copyFile,"cp %s  %s/bbtk_config.xml ",configXmlTmp,rootDirectory );
471         if (!Utilities::FileExists(rootDirectory))
472           {
473             //std::cout << "makeDir[" << makeDir << "]" << std::endl;
474             system(makeDir);
475           }
476         
477         if (!Utilities::FileExists(configPath))
478           {
479             system(copyFile);
480           }
481       }
482     return;
483     
484     // ------------------------------------------------------------------
485 #elif defined(WIN32)
486     
487     
488     // installed bbtk_path
489     char bbtk_path[100];
490     strcpy(bbtk_path, "\"c:\\Program Files\\BBTK\\bin\"");
491     char bbtk_path2[100];
492     strcpy(bbtk_path2, "c:\\Program Files\\BBTK\\bin");
493     
494     // rootDirectory
495     char rootDirectory[200];  
496     sprintf(rootDirectory, "%s\\.bbtk",getenv("USERPROFILE"));
497     //  std::cout << "[" << rootDirectory << "]" << std::endl;
498     
499     // configPath
500     char configPath[200];
501     sprintf(configPath, "%s\\bbtk_config.xml",rootDirectory);
502     
503     // makeDir
504     char makeDir[250];
505     sprintf( makeDir, "mkdir \"%s\" ", rootDirectory);
506     
507     // configXmlTmp
508     char configXmlTmp[250]; 
509     sprintf(configXmlTmp, "%s\\bbtk_config.xml.tmp", bbtk_path2);
510     
511     // copyFile
512     char copyFile[250];
513     
514     if (!Utilities::FileExists(configXmlTmp)) // bbtk_config.xml.tmp not found
515       {
516         if (!Utilities::FileExists(rootDirectory)) // .bbtk not found
517           {
518             system(makeDir);  // create .bbtk
519           }
520         
521         // if "bbtk_path/bbtk_config.xml.tmp" doesn't exist, hard-create a minimum version in .bbtk
522         CreateConfigXML( rootDirectory );// create .bbtk
523         return;
524       }  
525     
526     sprintf(copyFile,"copy %s\\bbtk_config.xml.tmp \"%s\"\\bbtk_config.xml ",bbtk_path,rootDirectory );
527     
528     int attribs = GetFileAttributes (rootDirectory);
529     bbtkMessage("Config",1,std::hex << attribs << " " << FILE_ATTRIBUTE_DIRECTORY << std::endl);
530     if ( attribs != 0xFFFFFFFF)
531       {
532         if ((attribs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY ) /// \TODO : check !
533           {
534             if ( GetFileAttributes( configPath ) == 0xFFFFFFFF)
535               {
536                 system(copyFile);  
537               } 
538           }
539       } 
540     else 
541       {
542         system(makeDir);
543         system(copyFile); 
544       }    
545     return;  
546     // ------------------------------------------------------------------    
547 #else
548 /// \todo  ConfigurationFile::InstallPath() : exit when for not WIN32 and not__GNUC__
549
550   return;    
551 #endif
552
553 }
554   //=========================================================================
555
556
557
558   //=========================================================================
559   // Gets the list of directories holding bb scripts, packages, dll, ... from the xml file
560   //      bbtk_config.xml
561   
562   void ConfigurationFile::Read(const std::string& filename)
563   {
564     
565     bbtkDebugMessage("Config",1,"ConfigurationFile::Read(" <<filename << ")" << std::endl);
566     
567     mConfig_xml_full_path = filename;
568     XMLResults* res = new XMLResults;
569     XMLNode BB = XMLNode::parseFile((XMLCSTR)filename.c_str(),(XMLCSTR)"config",res);
570     
571     if ( res->error != eXMLErrorNone ) 
572       {
573         std::string mess = GetErrorMessage(res,filename);
574         delete res;
575         bbtkDebugMessage("Config",1,mess<< std::endl);
576         bbtkError(mess);
577       }
578     delete res;
579     
580     bbtkDebugMessage("Config",1,"OK" << std::endl);
581   
582     int i,j;
583     
584     // Description
585     for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"description"); i++) 
586       {
587         std::string val;
588         GetTextOrClear(BB.getChildNode((XMLCSTR)"description",&j),val);
589         mDescription += val;
590       }    
591     
592     // Url
593     if( BB.nChildNode((XMLCSTR)"url") ) 
594       GetTextOrClear(BB.getChildNode((XMLCSTR)"url"),mUrl);
595     
596     // Data_Path
597     if( BB.nChildNode((XMLCSTR)"data_path") ) 
598       GetTextOrClear(BB.getChildNode((XMLCSTR)"data_path"),mData_path);
599     
600     // install_path
601     //  if( BB.nChildNode((XMLCSTR)"install_path") )
602     //   GetTextOrClear(BB.getChildNode((XMLCSTR)"install_path"),mInstall_path);
603     
604     // add user bbs paths
605     for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"bbs_path"); i++) 
606       {
607         std::string val;
608         GetTextOrClear(BB.getChildNode((XMLCSTR)"bbs_path",&j),val);
609         mBbs_paths.push_back(val);
610       }
611     
612     // package_paths
613     
614     // add user package path
615     for (i=0,j=0; i<BB.nChildNode((XMLCSTR)"package_path"); i++) 
616       {
617         std::string val;
618         GetTextOrClear(BB.getChildNode((XMLCSTR)"package_path",&j),val);
619         mPackage_paths.push_back(val);
620       }
621     
622     // default_temp_dir
623     if( BB.nChildNode((XMLCSTR)"default_temp_dir") ) 
624       GetTextOrClear(BB.getChildNode((XMLCSTR)"default_temp_dir"),mDefault_temp_dir);
625     
626     if ( mDefault_temp_dir == "$") // no value found in config_xml
627       {
628         size_t pos = mConfig_xml_full_path.find("bbtk_config.xml");
629         mDefault_temp_dir = mConfig_xml_full_path.substr (0,pos); 
630       }    
631
632     GetHelp(2);
633   }
634   //=========================================================================
635   
636   //=========================================================================
637   bool ConfigurationFile::AddPackagePathsAndWrite( const std::string& path )
638   {
639     bbtkDebugMessageInc("Config",9,
640                         "ConfigurationFile::AddPackagePathsAndWrite("
641                         <<path<<")"<<std::endl);
642     
643      XMLResults* res = new XMLResults;
644     XMLNode BB = 
645       XMLNode::parseFile((XMLCSTR)Get_config_xml_full_path().c_str(),
646                          (XMLCSTR)"config",res);
647     
648     if ( res->error != eXMLErrorNone ) 
649       {
650         std::string mess = GetErrorMessage(res,Get_config_xml_full_path());
651         delete res;
652         bbtkDebugMessage("Config",1,mess<< std::endl);
653         bbtkError(mess);
654       }
655    delete res;
656
657 #ifdef _WIN32
658     std::string bbs_path = path + "/bbs";
659 #else
660     std::string bbs_path = path + "/share/bbtk/bbs" ;
661 #endif
662     XMLNode BBSPATH = BB.addChild((XMLCSTR)"bbs_path");
663     BBSPATH.addText((XMLCSTR)bbs_path.c_str());
664     Utilities::replace(bbs_path, INVALID_FILE_SEPARATOR, VALID_FILE_SEPARATOR);
665     mBbs_paths.push_back(bbs_path);
666  
667 #ifdef _WIN32
668     std::string pack_path = path + "/bin";
669 #else
670     std::string pack_path = path ;
671 #endif
672     XMLNode PACKPATH = BB.addChild((XMLCSTR)"package_path");
673     PACKPATH.addText((XMLCSTR)pack_path.c_str());
674     Utilities::replace(pack_path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
675     mPackage_paths.push_back(pack_path);
676
677 #ifdef _WIN32
678     pack_path = path + "/Debug";
679     PACKPATH = BB.addChild((XMLCSTR)"package_path");
680     PACKPATH.addText((XMLCSTR)pack_path.c_str());
681     Utilities::replace(pack_path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
682     mPackage_paths.push_back(pack_path);
683     pack_path = path + "/Release";
684     PACKPATH = BB.addChild((XMLCSTR)"package_path");
685     PACKPATH.addText((XMLCSTR)pack_path.c_str());
686     Utilities::replace(pack_path,INVALID_FILE_SEPARATOR,VALID_FILE_SEPARATOR);
687     mPackage_paths.push_back(pack_path);
688 #endif
689
690
691     XMLError err = BB.writeToFile((XMLCSTR)Get_config_xml_full_path().c_str());
692     if ( err != eXMLErrorNone ) 
693       {
694         std::string mess = GetErrorMessage(res,Get_config_xml_full_path());
695         bbtkDebugMessage("Config",1,mess<< std::endl);
696         bbtkError(mess);
697       }
698
699     return true;
700   }
701   //=========================================================================
702
703   //=========================================================================
704   void ConfigurationFile::GetHelp(int level) const
705   {
706     bbtkDebugMessageInc("Config",9,"ConfigurationFile::GetHelp("<<level
707                         <<")"<<std::endl);
708     
709     const std::string config_xml_full_path      = Get_config_xml_full_path();    
710     const std::string description               = Get_description();
711     const std::string url                       = Get_doc_path();
712     const std::string data_path                 = Get_data_path();
713     const std::string default_temp_dir          = Get_default_temp_dir();    
714     const std::string file_separator            = Get_file_separator();    
715     const std::vector<std::string>bbs_paths     = Get_bbs_paths();
716     const std::vector<std::string>package_paths = Get_package_paths();
717     
718     bbtkMessage("Help",level, "============="   << std::endl);           
719     bbtkMessage("Help",level, "Configuration"   << std::endl);
720     bbtkMessage("Help",level, "============="   << std::endl);
721     bbtkMessage("Help",level, "bbtk_config.xml    : [" << config_xml_full_path  << "]" << std::endl); 
722     bbtkMessage("Help",level, "Documentation Path : [" << url             << "]" << std::endl);
723     bbtkMessage("Help",level, "Data Path          : [" << data_path       << "]" << std::endl);
724     bbtkMessage("Help",level, "Temp Directory     : [" << default_temp_dir << "]" << std::endl);
725     bbtkMessage("Help",level, "File Separator     : [" << file_separator  << "]" << std::endl);
726
727     std::vector<std::string>::const_iterator i;
728            
729     bbtkMessage("Help",level, "BBS Paths   " << std::endl);     
730     for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
731     {
732       bbtkMessage("Help",level,"--- ["<<*i<<"]"<<std::endl);
733     }    
734     
735     bbtkMessage("Help",level, "PACKAGE Paths : " << std::endl);     
736     for (i = package_paths.begin(); i!=package_paths.end(); ++i )
737     {
738       bbtkMessage("Help",level,"--- ["<<*i<<"]"<<std::endl);
739     }
740
741     bbtkDebugDecTab("Config",9);
742   }
743   //=========================================================================
744
745
746 } // namespace bbtk