RSC  0.14.5
Configuration.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2012, 2013, 2016 Jan Moringen <jmoringe@techfak.uni-bielefeld.de>
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "Configuration.h"
28 
29 #include <stdexcept>
30 
31 #include <boost/format.hpp>
32 #include <boost/filesystem/fstream.hpp>
33 
34 #include "../logging/Logger.h"
35 #include "../logging/LoggerFactory.h"
36 
37 #include "Environment.h"
38 #include "ConfigFileSource.h"
40 
41 using namespace std;
42 
43 using namespace rsc::logging;
44 
45 namespace rsc {
46 namespace config {
47 
49  static LoggerPtr logger
50  = logging::LoggerFactory::getInstance().getLogger("rsc.config.configure()");
51  return logger;
52 }
53 
54 void describeFileStream(const std::string& label,
55  const boost::filesystem::path& path,
56  const istream& stream) {
57  cerr << " " << label << " " << path << " "
58  << (stream ? "exists" : "does not exist") << endl;
59 }
60 
62  const string& configFileName,
63  const string& environmentVariablePrefix,
64  int argc,
65  const char** argv,
66  bool stripEnvironmentVariablePrefix,
67  const boost::filesystem::path& prefix) {
68  bool debug = getEnvironmentVariable("__CONFIG_DEBUG").get();
69 
70  // 0) In debug mode, header first.
71  if (debug) {
72  cerr << "Configuring with sources (lowest priority first)" << endl
73  << " 1. Configuration files" << endl;
74  }
75 
76  // 1) Try prefix-wide configuration file
77  // (lowest priority)
78  boost::filesystem::path
79  prefixWideFile(prefixConfigDirectory(prefix) / configFileName);
80  try {
81  boost::filesystem::ifstream stream(prefixWideFile);
82  if (debug) {
83  describeFileStream(" 1. Prefix wide config file",
84  prefixWideFile, stream);
85  }
86  if (stream) {
87  ConfigFileSource source(stream);
88  source.provideOptions(handler);
89  }
90  } catch (const runtime_error& e) {
92  "Failed to process prefix-wide configuration file `"
93  << prefixWideFile << "': " << e.what());
94  }
95 
96  // 2) Try user configuration file.
97  //
98  // The two instance of userConfigDirectory() / configFileName in
99  // the following code cannot be reduce into a variable assignment
100  // outside the try/catch block since the code can throw an
101  // exception.
102  bool isUserConfigDirOK = false;
103  try {
104  boost::filesystem::path userFile(userConfigDirectory()
105  / configFileName);
106  boost::filesystem::ifstream stream(userFile);
107  if (debug) {
108  describeFileStream(" 2. User config file", userFile, stream);
109  }
110  isUserConfigDirOK = true;
111  if (stream) {
112  ConfigFileSource source(stream);
113  source.provideOptions(handler);
114  }
115  } catch (const runtime_error& e) {
116  RSCWARN(getLogger(),
117  "Failed to process user-specific configuration file `"
118  << (isUserConfigDirOK
119  ? (userConfigDirectory() / configFileName).string()
120  : "<failed to determine user config dir>")
121  << "': " << e.what());
122  }
123 
124  // 3) Try configuration file in current directory.
125  {
126  boost::filesystem::ifstream stream(configFileName);
127  if (debug) {
128  describeFileStream(" 3. Current directory file",
129  configFileName, stream);
130  }
131  if (stream) {
132  ConfigFileSource source(stream);
133  source.provideOptions(handler);
134  }
135  }
136 
137  // 4) Add environment Variables
138  {
139  EnvironmentVariableSource source(environmentVariablePrefix,
140  stripEnvironmentVariablePrefix);
141  if (debug) {
142  cerr << " 2. Environment variables with prefix "
143  << environmentVariablePrefix << endl;
145  if (!matches.empty()) {
146  for (EnvironmentVariableSource::Matches::const_iterator it
147  = matches.begin(); it != matches.end(); ++it) {
148  cerr << " "
149  << it->getRawName() << " -> " << it->getValue();
150  }
151  } else {
152  cerr << " <none>";
153  }
154  cerr << endl;
155  }
156  source.provideOptions(handler);
157  }
158 
159  // 5) Command line
160  // (highest priority)
161  if (debug) {
162  cerr << " 3. Commandline options" << endl;
163  }
164  if (argc > 0) {
165  if (debug){
166  for (int i = 0; i < argc; ++i) {
167  cerr << " " << argv[i] << endl;
168  }
169  }
170  CommandLinePropertySource source(argc, argv);
171  source.provideOptions(handler);
172  } else {
173  if (debug) {
174  cerr << " <none>" << endl;
175  }
176  }
177 
178 }
179 
180 }
181 }
void provideOptions(OptionHandler &handler)
Implementations should pass all configuration options to handler.
path userConfigDirectory()
Return the canonical directory for configuration files of the user associated with the current proces...
void describeFileStream(const std::string &label, const boost::filesystem::path &path, const istream &stream)
Matches getMatches()
Return matching environment variables.
Objects of this class analyze the environment of the current process, finding environment variables w...
Definition: Environment.h:115
Objects of this class parse streams that contain configuration information in "ini-file" syntax...
A source for options from the command line using a -D java properties-like syntax.
void configure(OptionHandler &handler, const string &configFileName, const string &environmentVariablePrefix, int argc, const char **argv, bool stripEnvironmentVariablePrefix, const boost::filesystem::path &prefix)
Pass configuration options in from configuration files derived from configFileName and environment va...
void provideOptions(OptionHandler &handler)
Implementations should pass all configuration options to handler.
Implementations of this interface receive options from ConfigSource objects.
Definition: OptionHandler.h:43
STL namespace.
boost::shared_ptr< std::string > getEnvironmentVariable(const std::string &name)
Return the value of the environment value name or an empty pointer.
path prefixConfigDirectory(const path &prefix)
Definition: Environment.cpp:64
#define RSCWARN(logger, msg)
Definition: Logger.h:231
LoggerPtr getLogger()
Provides a hierarchical logging system with the possibility to install different backends, which are instances of LoggingSystem.
void handler(int signal)
void provideOptions(OptionHandler &handler)
Implementations should pass all configuration options to handler.
boost::shared_ptr< Logger > LoggerPtr
Definition: Logger.h:41