The Gaudi Framework  v29r0 (ff2e7097)
PathResolver.cpp
Go to the documentation of this file.
2 #include "GaudiKernel/System.h"
3 
4 #ifdef WIN32
5 // Disable warning
6 // C4996: 'std::copy': Function call with parameters that may be unsafe
7 // Probably coming from Boost classification.
8 #pragma warning( disable : 4996 )
9 #endif
10 
11 #include <iostream>
12 #include <stdlib.h>
13 #include <string>
14 #include <vector>
15 
16 #include <boost/algorithm/string/classification.hpp>
17 #include <boost/algorithm/string/split.hpp>
18 #include <boost/filesystem.hpp>
19 
20 namespace bf = boost::filesystem;
21 using namespace std;
22 
23 #ifdef _WIN32
24 static const char* path_separator = ",;";
25 #else
26 static const char* path_separator = ",:";
27 #endif
28 
29 //
31 //
32 
33 namespace System
34 {
35 
37 
39 
40  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41 
42  static bool PR_find( const bf::path& file, const string& search_list, PR_file_type file_type,
43  PathResolver::SearchType search_type, string& result )
44  {
45 
46  bool found( false );
47 
48  // look for file as specified first
49 
50  try {
51  if ( ( file_type == PR_regular_file && is_regular_file( file ) ) ||
52  ( file_type == PR_directory && is_directory( file ) ) ) {
53  result = bf::system_complete( file ).string();
54  return true;
55  }
56  } catch ( bf::filesystem_error /*err*/ ) {
57  }
58 
59  // assume that "." is always part of the search path, so check locally first
60 
61  try {
62  bf::path local = bf::initial_path() / file;
63  if ( ( file_type == PR_regular_file && is_regular_file( local ) ) ||
64  ( file_type == PR_directory && is_directory( local ) ) ) {
65  result = bf::system_complete( file ).string();
66  return true;
67  }
68  } catch ( bf::filesystem_error /*err*/ ) {
69  }
70 
71  // iterate through search list
72  vector<string> spv;
73  split( spv, search_list, boost::is_any_of( path_separator ), boost::token_compress_on );
74  for ( const auto& itr : spv ) {
75 
76  bf::path fp = itr / file;
77 
78  try {
79  if ( ( file_type == PR_regular_file && is_regular_file( fp ) ) ||
80  ( file_type == PR_directory && is_directory( fp ) ) ) {
81  result = bf::system_complete( fp ).string();
82  return true;
83  }
84  } catch ( bf::filesystem_error /*err*/ ) {
85  }
86 
87  // if recursive searching requested, drill down
88  if ( search_type == PathResolver::RecursiveSearch && is_directory( bf::path( itr ) ) ) {
89 
90  bf::recursive_directory_iterator end_itr;
91  try {
92  for ( bf::recursive_directory_iterator ritr( itr ); ritr != end_itr; ++ritr ) {
93 
94  // skip if not a directory
95  if ( !is_directory( bf::path( *ritr ) ) ) {
96  continue;
97  }
98 
99  bf::path fp2 = bf::path( *ritr ) / file;
100  if ( ( file_type == PR_regular_file && is_regular_file( fp2 ) ) ||
101  ( file_type == PR_directory && is_directory( fp2 ) ) ) {
102  result = bf::system_complete( fp2 ).string();
103  return true;
104  }
105  }
106  } catch ( bf::filesystem_error /*err*/ ) {
107  }
108  }
109  }
110 
111  return found;
112  }
113 
114  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
115 
116  string PathResolver::find_file( const std::string& logical_file_name, const std::string& search_path,
117  SearchType search_type )
118  {
119 
120  std::string path_list;
121  System::getEnv( search_path, path_list );
122 
123  return ( find_file_from_list( logical_file_name, path_list, search_type ) );
124  }
125 
126  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
127 
128  std::string PathResolver::find_file_from_list( const std::string& logical_file_name, const std::string& search_list,
129  SearchType search_type )
130  {
131  std::string result( "" );
132 
133  bf::path lfn( logical_file_name );
134 
135  /* bool found = */
136  PR_find( lfn, search_list, PR_regular_file, search_type, result );
137 
138  // The following functionality was in the original PathResolver, but I believe
139  // that it's WRONG. It extracts the filename of the requested item, and searches
140  // for that if the preceding search fails. i.e., if you're looking for "B/a.txt",
141  // and that fails, it will look for just "a.txt" in the search list.
142 
143  // if (! found && lfn.filename() != lfn ) {
144  // result = "";
145  // PR_find (lfn.filename(), search_list, PR_regular_file, search_type, result);
146  // }
147 
148  return ( result );
149  }
150 
151  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
152 
153  string PathResolver::find_directory( const std::string& logical_file_name, const std::string& search_path,
154  SearchType search_type )
155  {
156  std::string path_list;
157  System::getEnv( search_path, path_list );
158 
159  return ( find_directory_from_list( logical_file_name, path_list, search_type ) );
160  }
161 
162  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
163 
164  string PathResolver::find_directory_from_list( const std::string& logical_file_name, const std::string& search_list,
165  SearchType search_type )
166  {
167  std::string result;
168 
169  if ( !PR_find( logical_file_name, search_list, PR_directory, search_type, result ) ) {
170  result = "";
171  }
172 
173  return ( result );
174  }
175 
176  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
177 
178  PathResolver::SearchPathStatus PathResolver::check_search_path( const std::string& search_path )
179  {
180  std::string path_list;
181  if ( !System::getEnv( search_path, path_list ) ) return ( EnvironmentVariableUndefined );
182 
183  vector<string> spv;
184  boost::split( spv, path_list, boost::is_any_of( path_separator ), boost::token_compress_on );
185 
186  try {
187  for ( const auto& itr : spv ) {
188  bf::path pp( itr );
189  if ( !is_directory( pp ) ) {
190  return ( UnknownDirectory );
191  }
192  }
193  } catch ( bf::filesystem_error /*err*/ ) {
194  return ( UnknownDirectory );
195  }
196 
197  return ( Ok );
198  }
199 
200  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
201 
202  std::string PathResolverFindXMLFile( const std::string& logical_file_name )
203  {
204  return PathResolver::find_file( logical_file_name, "XMLPATH" );
205  }
206 
208  {
209  return PathResolver::find_file( logical_file_name, "DATAPATH" );
210  }
211 
212 } // System namespace
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:581
Note: OS specific details for environment resolution.
Definition: Debugger.h:19
GAUDI_API std::string PathResolverFindXMLFile(const std::string &logical_file_name)
STL namespace.
GAUDI_API std::string PathResolverFindDataFile(const std::string &logical_file_name)
T string(T...args)
STL class.