src/gui/utils/system_path.cpp

Go to the documentation of this file.
00001 /*  $Id: system_path.cpp 17696 2008-09-04 00:04:03Z dicuccio $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software / database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software / database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors:  Robert G. Smith
00027  *
00028  * File Description:
00029  *    CSystemPath -- System dependent functions needed by CGBenchApp, the main
00030  *                         application class for GBENCH
00031  */
00032 
00033 #include <ncbi_pch.hpp>
00034 #include <gui/utils/system_path.hpp>
00035 
00036 #include <corelib/ncbiapp.hpp>
00037 #include <corelib/ncbienv.hpp>
00038 #include <corelib/ncbifile.hpp>
00039 
00040 #if defined(NCBI_OS_DARWIN)
00041 #   ifdef NCBI_COMPILER_METROWERKS
00042 #   define __NOEXTENSIONS__
00043 #   endif
00044 #   include <Carbon/Carbon.h>
00045 #endif
00046 
00047 BEGIN_NCBI_SCOPE
00048 
00049 CSystemPath::TAliasMap CSystemPath::sm_AliasMap;
00050 
00051 void CSystemPath::BindAlias(const string& alias, const string& path)
00052 {
00053     sm_AliasMap[alias] = path;
00054 }
00055 
00056 
00057 //
00058 // ResolvePath()
00059 // this function performs any standard app-specific directory mapping
00060 // so that we can use a series of standard aliases for directory names
00061 //
00062 string CSystemPath::ResolvePath(const string& path)
00063 {
00064     string  path1, path2;
00065     string  path_delim("\\/");
00066     NStr::SplitInTwo(path, path_delim, path1, path2);
00067     if ( !path1.empty() ) {
00068         return ResolvePath(path1, path2);
00069     }
00070 
00071     return path;
00072 }
00073 
00074 
00075 string CSystemPath::ResolvePath(const string& path,
00076                                 const string& subdir)
00077 {
00078     string ret_val(path);
00079     TAliasMap::const_iterator it = sm_AliasMap.find(path);
00080     if (it != sm_AliasMap.end()) {
00081         ret_val = it->second;
00082     } else {
00083         if (ret_val == "<std>") {
00084             ret_val = GetStdPath();
00085         } else if (ret_val == "<home>") {
00086             ret_val = GetHomePath();
00087         } else if (ret_val == "<pkgdir>") {
00088             ret_val = GetStdPath();
00089             ret_val += CDir::GetPathSeparator();
00090             ret_val += "packages";
00091         } else if (ret_val == "<res>") {
00092             ret_val = GetResourcePath();
00093         }
00094     }
00095 
00096     if ( !subdir.empty() ) {
00097         ret_val += CDirEntry::GetPathSeparator();
00098         ret_val += subdir;
00099     }
00100     return ret_val;
00101 }
00102 
00103 
00104 //
00105 // ResolvePathExisting ensures that a named file exists
00106 //
00107 
00108 template <class iterator>
00109 string x_ResolveExisting(iterator begin, iterator end)
00110 {
00111     for ( ;  begin != end;  ++begin) {
00112         string p(*begin);
00113         p = NStr::TruncateSpaces(p);
00114         string tmp = CSystemPath::ResolvePath(p);
00115 
00116         // check for existence
00117         CDirEntry entry(tmp);
00118         if (entry.Exists()) {
00119             return tmp;
00120         }
00121     }
00122     return string();
00123 }
00124 
00125 string CSystemPath::ResolvePathExisting(const string& path,
00126                                         const string& delim)
00127 {
00128     list<string> toks;
00129     NStr::Split(path, delim, toks);
00130     return x_ResolveExisting(toks.begin(), toks.end());
00131 }
00132 
00133 
00134 string CSystemPath::ResolvePathExisting(const vector<string>& paths)
00135 {
00136     return x_ResolveExisting(paths.begin(), paths.end());
00137 }
00138 
00139 
00140 string CSystemPath::ResolvePathExisting(const list<string>& paths)
00141 {
00142     return x_ResolveExisting(paths.begin(), paths.end());
00143 }
00144 
00145 
00146 // the GBench installation directory. Usually the parent of the App Path.
00147 // corresponds to the <std> alias in ResolvePath().
00148 string CSystemPath::GetStdPath(void)
00149 {
00150     string ret_val;
00151     CNcbiApplication  *myApp = CNcbiApplication::Instance();
00152     _ASSERT(myApp);
00153 
00154     // First, was the value set in the environment variable $NCBI_GBENCH_HOME
00155     ret_val = myApp->GetEnvironment().Get(string("NCBI_GBENCH_HOME"));
00156 
00157     if (ret_val.empty()) {
00158 
00159         // Next, look at the application's own location.
00160         ret_val = myApp->GetArguments().GetProgramDirname();
00161 
00162         if (!ret_val.empty()) {
00163             // strip off the bin directory, if it is there.
00164             string::size_type pos = ret_val.rfind("bin");
00165             if (pos != string::npos  &&  pos == ret_val.length() - 4) {
00166                 ret_val.erase(pos);
00167             }
00168 
00169             // Remove trailing "/"
00170             while ( (pos = ret_val.find_last_of("\\/")) ==
00171                      ret_val.length() - 1) {
00172                 ret_val.erase(pos);
00173             }
00174         }
00175 
00176         // Hmmm... We aren't where we should be.
00177         if (ret_val.empty()) {
00178             LOG_POST(Warning
00179                      << "Can't identify the application's execution path.  "
00180                      "Some components may be unavailable.");
00181         }
00182     }
00183     return ret_val;
00184 }
00185 
00186 
00187 string CSystemPath::GetResourcePath()
00188 {
00189     string path = GetStdPath();
00190     path += CDirEntry::GetPathSeparator();
00191     path += "share";
00192     path += CDirEntry::GetPathSeparator();
00193     path += "gbench";
00194     return path;
00195 }
00196 
00197 
00198 string CSystemPath::GetUserPath(void)
00199 {
00200     return CDir::GetHome();
00201 }
00202 
00203 
00204 // The place gbench keeps stuff.
00205 // corresponds to the <home> alias in ResolvePath().
00206 //   Is NOT the same as the user's home directory.
00207 //   That is returned by CDir::GetHome()
00208 string CSystemPath::GetHomePath(void)
00209 {
00210     string ret_val(GetUserPath());
00211 #if defined(NCBI_OS_UNIX)   &&  ! defined(NCBI_OS_DARWIN)
00212     ret_val += ".gbench2";
00213 #elif defined(NCBI_OS_DARWIN)
00214     OSErr       err;
00215     FSRef       appsuppFSRef;
00216     char        appsuppPath[1024];
00217 
00218 
00219     // Get the path to the Application Support folder for this user.
00220     //
00221     err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder,
00222                      &appsuppFSRef);
00223     if (err == noErr) {
00224         err = FSRefMakePath(&appsuppFSRef, (UInt8 *) appsuppPath, 1024);
00225     }
00226     if (err == noErr) {
00227         ret_val = appsuppPath;
00228         // not a hidden folder
00229         ret_val = CDirEntry::MakePath(ret_val, "gbench2");
00230     } else {
00231         // Problems getting the Mac Application Support folder?
00232         // use ~/.gbench/ just like on other Unixes.
00233         ret_val = CDirEntry::MakePath(ret_val, ".gbench2");
00234     }
00235 
00236 #elif defined(NCBI_OS_MSWIN)
00237     ret_val += "GenomeWorkbench2";
00238 #else
00239 #error "platform unrecognized"
00240 #endif
00241     return ret_val;
00242 }
00243 
00244 
00245 ///
00246 /// PATH variable manipulators
00247 ///
00248 void CSystemPath::AddToPath(const string& path, EPathMode mode)
00249 {
00250     CNcbiApplication* app = CNcbiApplication::Instance();
00251     string base_path;
00252     if (app) {
00253         base_path = app->GetEnvironment().Get("PATH");
00254     } else {
00255         const char* p = getenv("PATH");
00256         if (p) {
00257             base_path = p;
00258         }
00259     }
00260 
00261     const char path_sep =
00262 #ifdef NCBI_OS_MSWIN
00263         ';'
00264 #else
00265         ':'
00266 #endif
00267         ;
00268 
00269     string::size_type pos = base_path.find(path);
00270     if ( (pos == 0  && mode == ePath_Prepend)  ||
00271          (pos + path.length() == base_path.length()  &&  mode == ePath_Append) ) {
00272         return;
00273     }
00274 
00275     while ( (pos = base_path.find(path, pos)) != string::npos) {
00276         if (pos > 0  &&  base_path[pos - 1] != path_sep) {
00277             pos += path.length();
00278             continue;
00279         }
00280         if (pos + path.length() < base_path.length()  &&  base_path[pos + 1] != path_sep) {
00281             pos += path.length();
00282             continue;
00283         }
00284 
00285         base_path.erase(pos, path.length());
00286     }
00287 
00288     switch (mode) {
00289     case ePath_Prepend:
00290         {{
00291             string p(path);
00292             p += path_sep;
00293             p += base_path;
00294             base_path = p;
00295         }}
00296         break;
00297 
00298     default:
00299     case ePath_Append:
00300         base_path += path_sep;
00301         base_path += path;
00302         break;
00303     }
00304 
00305     if (app) {
00306         CNcbiEnvironment& env = app->SetEnvironment();
00307         env.Set("PATH", base_path);
00308     } else {
00309         /// this does potentially leak, but the ANSI standard on putenv is unclear
00310         /// on the handling of the memory passed to putenv, and thus it is safer
00311         /// to leak a small amount than risk a bad pointer passed to the C runtime
00312         base_path = "PATH=" + base_path;
00313         putenv(strdup(base_path.c_str()));
00314     }
00315 }
00316 
00317 
00318 END_NCBI_SCOPE
00319 
00320 

Generated on Wed Dec 9 04:33:21 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:18:02 2009 by modify_doxy.py rev. 173732