LocationUtils.cpp
Go to the documentation of this file.
1 #include <NovaDAQUtilities/LocationUtils.h>
2 #include <boost/algorithm/string.hpp>
3 #include <boost/algorithm/string/trim.hpp>
4 #include <boost/filesystem.hpp>
5 #include <iostream>
6 #include <wordexp.h>
7 
8 namespace BFS = boost::filesystem;
9 
10 namespace novadaq {
11 
17 
18 /**
19  * Translates the specified URL to a generally accepted form.
20  *
21  * At the moment, the only translation that is supported is to
22  * convert a URL of the form srt://relativePath/filename to
23  * ${SRT_PRIVATE_RELEASE}/relativePath/filename or
24  * ${SRT_PUBLIC_RELEASE}/relativePath/filename depending
25  * on whether a private (test) release has been set up *and*
26  * the specified file or directory exists in the test release.
27  * All other URLs are simply returned with no modification.
28  *
29  * @param sourceURL The URL string to translate.
30  *
31  * @return The modified URL string.
32  */
34 
35  // make a copy of the URL without any leading spaces (just in case)
36  std::string trimmedURL = boost::algorithm::trim_left_copy(sourceURL);
37 
38  // if the URL uses our SRT notation, do the needed translation
39  if (trimmedURL.substr(0, 6) == "srt://") {
40  trimmedURL.erase(0, 5);
41 
42  char* rootPath = getenv("SRT_PRIVATE_CONTEXT");
43  if (rootPath == 0 || strcmp(rootPath, ".") == 0) {
44  rootPath = getenv("SRT_PUBLIC_CONTEXT");
45  }
46  else {
47  std::string fileInTestRelease(rootPath);
48  fileInTestRelease.append(trimmedURL);
49  if (! BFS::exists(fileInTestRelease)) {
50  rootPath = getenv("SRT_PUBLIC_CONTEXT");
51  }
52  }
53 
54  if (rootPath != 0) {
55  trimmedURL.insert(0, rootPath);
56  return trimmedURL;
57  }
58  }
59 
60  // if the URL uses our SRT notation, do the needed translation
61  if (trimmedURL.substr(0, 6) == "xml://") {
62  trimmedURL.erase(0, 5);
63 
64  char* rootPath = getenv("NOVADAQXML_DIR");
65  if (rootPath) {
66  trimmedURL.insert(0, rootPath);
67  return trimmedURL;
68  }
69  }
70 
71  // if we failed to do the translation, or none was needed, simply
72  // return the input URL
73  return sourceURL;
74 }
75 
76 /**
77  * Replaces environmental variable names in the input string with
78  * their values from the current shell environment.
79  *
80  * *NOTE* that for this replacement to work, environmental
81  * variable names must be surrounded by "${" and "}".
82  *
83  * For example:
84  * - ${SRT_PRIVATE_CONTEXT}/${HOST}
85  *
86  * @param sourceString The input string.
87  *
88  * @return The modified string.
89  */
91 
92  // make a copy of the string
93  std::string workString = sourceString;
94 
95  // loop through all of the env vars in the string
96  std::string::size_type startPos = workString.find("${", 0);
97  while (startPos != std::string::npos) {
98  std::string::size_type endPos = workString.find("}", startPos+1);
99  if (endPos != std::string::npos &&
100  endPos > startPos) {
101  std::string::size_type length = endPos - startPos - 2;
102 
103  std::string envVarName = workString.substr(startPos+2, length);
104  std::string toBeReplaced = workString.substr(startPos, length+3);
105 
106  char* envVarPtr = getenv(envVarName.c_str());
107  if (envVarPtr != 0) {
108  std::string replacementString(envVarPtr);
109  boost::replace_all(workString, toBeReplaced,
110  replacementString);
111  }
112  }
113 
114  startPos = workString.find("${", startPos+1);
115  }
116 
117  return workString;
118 }
119 
120 /**
121  * Runs the word expansion function on the input string
122  * (<code>wordexp</code>). This function provides tilde
123  * expansion and environmental variable replacement, among
124  * other things.
125  *
126  * @param sourceString The input string.
127  *
128  * @return The modified string.
129  */
131 
132  std::string resultString = sourceString;
133 
134  wordexp_t result;
135  int status = wordexp(sourceString.c_str(), &result, WRDE_NOCMD);
136  if (status == 0) {
137  resultString = "";
138  for (uint32_t idx = 0; idx < result.we_wordc; ++idx) {
139  std::string tmpString(result.we_wordv[idx]);
140  resultString.append(tmpString);
141  }
142  }
143 
144  wordfree(&result);
145  return resultString;
146 }
147 
148 /**
149  * Finds the first occurrence of the specified file using a standard
150  * set of possible locations. This method returns true if an instance of
151  * the file was found and returns false if not. The location of the
152  * instance of the file that was found is returned in the
153  * locationOfFoundInstance argument.
154  *
155  * NOTE that if the file is found on disk, a "file://" prefix is currently
156  * *NOT* included in the returned locationOfFoundInstance string. It simply
157  * contains the full path to the requested file.
158  *
159  * The current search order is the following:
160  * <ol>
161  * <li> `pwd`/filePath (if the filePath does *not* have a leading slash)
162  * <li> filePath (if the filePath does have a leading slash)
163  * <li> srt://filePath (this translates to ${SRT_PRIVATE_CONTEXT}/filePath
164  * followed by ${SRT_PUBLIC_CONTEXT}/filePath)
165  * <li> http://filePath (not implemented yet)
166  * <li> ftp://filePath (not implemented yet)
167  * </ol>
168  *
169  * If suggested prefixes are supplied, and the searches listed above do
170  * not initially succeed in locating the file, then the search is repeated
171  * using modifiedFilePath = suggestedPrefix + filePath for each
172  * suggested prefix until the file is found or the list is exhausted.
173  *
174  * @param filePath The name of the file to be located. This string may
175  * contain optional absolute or relative path information.
176  * @param locationOfFoundInstance The URL of the first instance of the
177  * file that was found.
178  * @param suggestedPrefixes A list of prefixes that should be prepended
179  * to the filePath during searching.
180  *
181  * @return true if the file was found, false if not.
182  */
183 bool LocationUtils::
184 findFile(const std::string& filePath,
185  std::string& locationOfFoundInstance,
186  const std::vector<std::string>& suggestedPrefixes) {
187 
188  // first, try the search without using any suggested prefix
189  if (LocationUtils::_findFile(filePath, locationOfFoundInstance)) {
190  return true;
191  }
192 
193  // next, try the search with each suggested prefix
194  for (uint32_t idx = 0; idx < suggestedPrefixes.size(); ++idx) {
195  std::string modifiedFilePath = suggestedPrefixes[idx] + filePath;
196  if (LocationUtils::_findFile(modifiedFilePath,
197  locationOfFoundInstance)) {
198  return true;
199  }
200  }
201 
202  // return false to indicate that we couldn't find the file
203  return false;
204 }
205 
206 /**
207  * Finds the first occurrence of the specified file using a standard
208  * set of possible locations. This method returns true if an instance of
209  * the file was found and returns false if not. The location of the
210  * instance of the file that was found is returned in the
211  * locationOfFoundInstance argument.
212  *
213  * @see findFile(const std::string&, std::string&, const std::vector<std::string>&)
214  */
216  std::string& locationOfFoundInstance) {
217  std::vector<std::string> emptyList;
218  return LocationUtils::findFile(filePath, locationOfFoundInstance,
219  emptyList);
220 }
221 
222 /**
223  * Does the work of searching for a file in a pre-defined set of locations.
224  */
226  std::string& locationOfFoundInstance) {
227 
228  // initialization
229  std::string workString;
230  std::string expandedPath = wordExpansion(filePath);
231  std::string trimmedFilePath = boost::algorithm::trim_copy(expandedPath);
232 
233  // look for the file without any special protocol prefix
234  if (trimmedFilePath.substr(0, 1) == "/") {
235  if (BFS::exists(trimmedFilePath)) {
236  locationOfFoundInstance = trimmedFilePath;
237  return true;
238  }
239  }
240  else {
241  BFS::path currentPath = BFS::current_path();
242 #if ( BOOST_FILESYSTEM_VERSION == 2 )
243  workString = currentPath.file_string();
244 #else
245  workString = currentPath.string();
246 #endif
247  workString.append("/" + trimmedFilePath);
248  if (BFS::exists(workString)) {
249  locationOfFoundInstance = workString;
250  return true;
251  }
252  }
253 
254  // look for the file in SRT directories
255  workString = SRT_PROTOCOL_PREFIX + trimmedFilePath;
256  workString = translateURL(workString);
257  if (BFS::exists(workString)) {
258  locationOfFoundInstance = workString;
259  return true;
260  }
261 
262  // look for the file in xml subdir of Offline release of Online packages
263  workString = XML_PROTOCOL_PREFIX + trimmedFilePath;
264  workString = translateURL(workString);
265  if (BFS::exists(workString)) {
266  locationOfFoundInstance = workString;
267  return true;
268  }
269 
270  return false;
271 }
272 
273 } // end of namespace novadaq
static const std::string FILE_PROTOCOL_PREFIX
Definition: LocationUtils.h:21
int status
Definition: fabricate.py:1613
static std::string wordExpansion(const std::string &sourceString)
static bool findFile(const std::string &filePath, std::string &locationOfFoundInstance)
std::string trim_copy(std::string source, std::string const &t=" ")
Definition: trim.h:66
static bool _findFile(const std::string &filePath, std::string &locationOfFoundInstance)
bool replace_all(std::string &in, std::string const &from, std::string const &to)
Replace all occurrences of from in string with to.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Definition: typedefs.hpp:11
length
Definition: demo0.py:21
static const std::string HTTP_PROTOCOL_PREFIX
Definition: LocationUtils.h:22
std::string getenv(std::string const &name)
const std::string path
Definition: plot_BEN.C:43
static const std::string FTP_PROTOCOL_PREFIX
Definition: LocationUtils.h:23
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
static const std::string SRT_PROTOCOL_PREFIX
Definition: LocationUtils.h:20
static std::string replaceEnvVars(const std::string &sourceString)
static std::string translateURL(const std::string &sourceURL)
static const std::string XML_PROTOCOL_PREFIX
Definition: LocationUtils.h:24
std::string trim_left_copy(std::string source, std::string const &t=" ")
Definition: trim.h:60