JayBeams  0.1
Another project to have fun coding.
config_files_location.hpp
Go to the documentation of this file.
1 #ifndef jb_config_files_location_hpp
2 #define jb_config_files_location_hpp
3 
4 #include <boost/filesystem/path.hpp>
5 #include <cstdlib>
6 #include <string>
7 #include <vector>
8 
9 namespace jb {
10 
11 /**
12  * Define the functor to read configuration variables from the
13  * environment. This is mostly to provide a dependency injection
14  * point for tests.
15  */
17  char const* operator()(char const* name);
18 };
19 
20 /**
21  * Define the functor to validate if paths are readable. This is
22  * mostly to provide a dependency injection point for tests.
23  */
25  bool operator()(boost::filesystem::path const& path);
26 };
27 
28 /**
29  * Define the configuration file search algorithm for JayBeams.
30  *
31  * Please @see config_files_location_base, this class just refactors
32  * the implementation to a non-template class.
33  */
35 public:
36  std::vector<boost::filesystem::path> const& search_path() const {
37  return search_path_;
38  }
39 
40 protected:
41  /**
42  * Constructor.
43  *
44  * @param argv0 the path for the current program (typically
45  * argv[0])
46  * @param program_root_variable the name of the *_ROOT environment variable
47  * used by this program, it can be null if the program does not
48  * provide any.
49  * @param getenv a function to fetch the values of environment
50  * variables. Just used for dependency injection.
51  */
53  boost::filesystem::path const& argv0,
54  std::function<char const*(char const*)> getenv,
55  char const* program_root_variable);
56 
57  /**
58  * Constructor.
59  *
60  * @param argv0 the path for the current program (typically
61  * argv[0])
62  * @param getenv a function to fetch the values of environment
63  * variables. Just used for dependency injection.
64  */
66  boost::filesystem::path const& argv0,
67  std::function<char const*(char const*)> getenv);
68 
69 private:
70  std::vector<boost::filesystem::path> search_path_;
71 };
72 
73 /**
74  * Compute the directories where a configuration file can be found.
75  *
76  * JayBeams configuration files can be located in multiple places:
77  * # Each program defines its own '*_ROOT' environment variable, the
78  * files are searched there if the variable is defined, otherwise
79  * # the files are found in the generic 'JAYBEAMS_ROOT' location, if
80  * that environment variable is defined, otherwise
81  * # the files are found in the installation directory, if the
82  * directory exists, otherwise,
83  * # the files are found relative to the program path name.
84  *
85  * This class implements the algorithms to (a) compute the valid list
86  * of directories for a given program, and (b) select which
87  * configuration file to load.
88  *
89  * We use some template parameters for dependency injection, it is
90  * hard to test the interaction with the file system (and the
91  * environment variables) without them.
92  *
93  * @tparam getenv_functor the functor used to fetch the value of
94  * environment variables. This is used for dependency injection
95  * during testing.
96  * @tparam validator_functor the functor used to validate if a given
97  * path is readable. This is used for dependency injection during
98  * testing.
99  */
100 template <
101  typename getenv_functor = default_getenv,
102  typename validator_functor = default_validator>
104 public:
105  /**
106  * Constructor.
107  *
108  * Build the search path given the program path and the name of its
109  * preferred environment variable.
110  *
111  * @param argv0 the program path, typically argv[0] from main()
112  * @param program_root_variable the name of the preferred
113  * environment variable for this program, i.e., its *_ROOT variable.
114  * @param getenv the functor object to use
115  */
117  boost::filesystem::path const& argv0, char const* program_root_variable,
118  getenv_functor getenv)
119  : config_files_locations_base(argv0, getenv, program_root_variable) {
120  }
121 
122  /**
123  * Constructor.
124  *
125  * Build the search path given the program path. Used in programs
126  * that do not have a preferred *_ROOT environment variable.
127  *
128  * @param argv0 the program path, typically argv[0] from main()
129  * @param getenv the functor object to use
130  */
132  boost::filesystem::path const& argv0, getenv_functor getenv)
133  : config_files_locations_base(argv0, getenv) {
134  }
135 
136  ///@{
137  /**
138  * Convenience constructors.
139  *
140  * Apply common conversions and create functors as needed.
141  */
143  boost::filesystem::path const& argv0, char const* program_root_variable)
144  : config_files_locations(argv0, program_root_variable, getenv_functor()) {
145  }
146  explicit config_files_locations(boost::filesystem::path const& argv0)
147  : config_files_locations(argv0, getenv_functor()) {
148  }
150  char const* argv0, char const* program_root_variable,
151  getenv_functor getenv)
153  boost::filesystem::path(argv0), program_root_variable, getenv) {
154  }
155  config_files_locations(char const* argv0, char const* program_root_variable)
157  boost::filesystem::path(argv0), program_root_variable,
158  getenv_functor()) {
159  }
160  config_files_locations(char const* argv0, getenv_functor getenv)
161  : config_files_locations_base(boost::filesystem::path(argv0), getenv) {
162  }
163  explicit config_files_locations(char const* argv0)
165  boost::filesystem::path(argv0), getenv_functor()) {
166  }
167  //@}
168 
169  /**
170  * Find a configuration file in the computed search path.
171  *
172  * @param filename the basename of the configuration file.
173  * @param validator the functor to use for validation
174  *
175  * @returns the path to load
176  * @throws std::runtime_error if no suitable file was found.
177  */
178  boost::filesystem::path find_configuration_file(
179  std::string const& filename, validator_functor validator) const {
180  for (auto const& path : search_path()) {
181  auto full = path / filename;
182  if (validator(full)) {
183  return full;
184  }
185  }
186  std::string msg("Cannot find file in search path: ");
187  msg += filename;
188  throw std::runtime_error(msg);
189  }
190 
191  /**
192  * Find a configuration file in the computed search path.
193  *
194  * @param filename the basename of the configuration file.
195  *
196  * @returns the path to load
197  * @throws std::runtime_error if no suitable file was found.
198  */
199  boost::filesystem::path
200  find_configuration_file(std::string const& filename) const {
201  return find_configuration_file(filename, validator_functor());
202  }
203 };
204 
205 /**
206  * Return the system configuration directory.
207  *
208  * Typically this is something like /etc or /usr/local/etc but it can
209  * change depending on how JayBeams was configured and the target
210  * platform.
211  */
212 char const* sysconfdir();
213 
214 /**
215  * Return the binary installation directory directory.
216  *
217  * Typically this is something like /usr/bin or /usr/local/bin but it
218  * can change depending on how JayBeams was configured and the
219  * target platform.
220  */
221 char const* bindir();
222 
223 } // namespace jb
224 
225 #endif // jb_config_files_location_hpp
config_files_locations(char const *argv0)
config_files_locations(boost::filesystem::path const &argv0)
boost::filesystem::path find_configuration_file(std::string const &filename, validator_functor validator) const
Find a configuration file in the computed search path.
std::vector< boost::filesystem::path > const & search_path() const
Define the functor to validate if paths are readable.
config_files_locations(boost::filesystem::path const &argv0, char const *program_root_variable)
Convenience constructors.
std::vector< boost::filesystem::path > search_path_
config_files_locations(char const *argv0, char const *program_root_variable)
char const * operator()(char const *name)
boost::filesystem::path find_configuration_file(std::string const &filename) const
Find a configuration file in the computed search path.
Define the configuration file search algorithm for JayBeams.
config_files_locations(char const *argv0, char const *program_root_variable, getenv_functor getenv)
char const * bindir()
Return the binary installation directory directory.
config_files_locations(boost::filesystem::path const &argv0, getenv_functor getenv)
Constructor.
config_files_locations(boost::filesystem::path const &argv0, char const *program_root_variable, getenv_functor getenv)
Constructor.
char const * sysconfdir()
Return the system configuration directory.
config_files_locations(char const *argv0, getenv_functor getenv)
Define the functor to read configuration variables from the environment.
Compute the directories where a configuration file can be found.
The top-level namespace for the JayBeams library.
Definition: as_hhmmss.hpp:7