00001 /* 00002 * Copyright (C) 2003-2009 Olivier Boudeville 00003 * 00004 * This file is part of the Ceylan library. 00005 * 00006 * The Ceylan library is free software: you can redistribute it and/or modify 00007 * it under the terms of either the GNU Lesser General Public License or 00008 * the GNU General Public License, as they are published by the Free Software 00009 * Foundation, either version 3 of these Licenses, or (at your option) 00010 * any later version. 00011 * 00012 * The Ceylan library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License and the GNU General Public License 00016 * for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License and the GNU General Public License along with the Ceylan library. 00020 * If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 * Author: Olivier Boudeville (olivier.boudeville@esperide.com) 00023 * 00024 */ 00025 00026 00027 #include "CeylanFileLocator.h" 00028 00029 #include "CeylanFile.h" // for ExistsAsFileOrSymbolicLink 00030 #include "CeylanDirectory.h" // for JoinPath 00031 #include "CeylanStringUtils.h" // for formatStringList 00032 #include "CeylanLogPlug.h" // for LogPlug 00033 #include "CeylanEnvironmentVariables.h" // for getEnvironmentVariable 00034 00035 00036 00037 #ifdef CEYLAN_USES_CONFIG_H 00038 #include "CeylanConfig.h" // for CEYLAN_DEBUG_DEMANGLE, etc. 00039 #endif // CEYLAN_USES_CONFIG_H 00040 00041 00042 00043 #if CEYLAN_ARCH_NINTENDO_DS 00044 #include "CeylanConfigForNintendoDS.h" // for iprintf, CEYLAN_DS_LOG 00045 #endif // CEYLAN_ARCH_NINTENDO_DS 00046 00047 00048 00049 using std::string ; 00050 using std::list ; 00051 00052 using namespace Ceylan::System ; 00053 using namespace Ceylan::Log ; 00054 00055 00056 00057 /* 00058 * UNIX path separator is ':', Windows one is ';'. 00059 * 00060 */ 00061 00062 00063 FileLocatorException::FileLocatorException( const std::string & message ) : 00064 SystemException( message ) 00065 { 00066 00067 } 00068 00069 00070 FileLocatorException::~FileLocatorException() throw() 00071 { 00072 00073 } 00074 00075 00076 00077 00078 FileLocator::FileLocator() : 00079 _paths() 00080 { 00081 00082 } 00083 00084 00085 00086 FileLocator::FileLocator( const string & variableName, char separator ) : 00087 _paths() 00088 { 00089 00090 #if CEYLAN_ARCH_NINTENDO_DS 00091 00092 /* 00093 * No environment variables on the DS, so no path to consider: 00094 00095 LogPlug::warning( "FileLocator constructor: running on the DS, " 00096 "hence environment variable '" + variableName + "' is ignored." ) ; 00097 * 00098 * However this log message has been commented out, as file locators are 00099 * often created in global variables (ex: C++ static initializers), which 00100 * implies that the log system may not be started yet. 00101 * 00102 */ 00103 00104 #else // CEYLAN_ARCH_NINTENDO_DS 00105 00106 addPathsFromEnvironmentVariable( variableName, separator ) ; 00107 00108 #endif // CEYLAN_ARCH_NINTENDO_DS 00109 00110 } 00111 00112 00113 00114 FileLocator::~FileLocator() throw() 00115 { 00116 00117 } 00118 00119 00120 00121 bool FileLocator::addPath( const string & newPath ) 00122 { 00123 00124 for ( list<string>::const_iterator it = _paths.begin(); 00125 it != _paths.end(); it++ ) 00126 if ( (*it) == newPath ) 00127 return false ; 00128 00129 _paths.push_back( newPath ) ; 00130 00131 return true ; 00132 00133 } 00134 00135 00136 00137 bool FileLocator::addPaths( const std::list<std::string> & paths ) 00138 { 00139 00140 bool res = false ; 00141 00142 for ( list<string>::const_iterator it = paths.begin(); 00143 it != paths.end(); it++ ) 00144 res |= addPath( (*it ) ) ; 00145 00146 return res ; 00147 00148 } 00149 00150 00151 00152 bool FileLocator::addPathsFromEnvironmentVariable( 00153 const std::string & variableName, char separator ) 00154 { 00155 00156 return addPaths( Ceylan::split( getEnvironmentVariable( variableName ), 00157 separator ) ) ; 00158 00159 } 00160 00161 00162 00163 bool FileLocator::removePath( const string & pathToRemove ) 00164 { 00165 00166 // Comparison on string content, not pointers: 00167 for ( list<string>::iterator it = _paths.begin(); it != _paths.end(); it++ ) 00168 if ( (*it) == pathToRemove ) 00169 { 00170 // Iterator will not be used anymore afterwards: 00171 _paths.erase( it ) ; 00172 return true ; 00173 } 00174 00175 return false ; 00176 00177 } 00178 00179 00180 00181 string FileLocator::find( const string & filename ) const 00182 { 00183 00184 string fullPath ; 00185 00186 for ( list<string>::const_iterator it = _paths.begin(); 00187 it != _paths.end(); it++ ) 00188 { 00189 00190 fullPath = Directory::JoinPath( (*it), filename ) ; 00191 00192 //LogPlug::debug( "FileLocator::find: testing '" + fullPath + "'." ) ; 00193 00194 if ( File::ExistsAsFileOrSymbolicLink( fullPath ) ) 00195 return fullPath ; 00196 } 00197 00198 throw FileLocatorException( "File '" + filename 00199 + "' could not be found through following Locator: " + toString() ) ; 00200 00201 } 00202 00203 00204 00205 const std::list<std::string> & FileLocator::getPaths() const 00206 { 00207 00208 return _paths ; 00209 00210 } 00211 00212 00213 00214 const string FileLocator::toString( Ceylan::VerbosityLevels level ) const 00215 { 00216 00217 if ( _paths.empty() ) 00218 return "Empty File locator" ; 00219 00220 return "File locator with following registered directories: " 00221 + Ceylan::formatStringList( _paths ) ; 00222 00223 } 00224