RSC  0.12.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Configurator.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project.
4  *
5  * Copyright (C) 2012, 2014 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 "Configurator.h"
28 
29 #include <boost/format.hpp>
30 
31 #include <boost/tokenizer.hpp>
32 
33 #include "../runtime/ContainerIO.h"
34 
35 #include "../logging/LoggerFactory.h"
36 
37 using namespace std;
38 
39 using namespace boost;
40 using namespace boost::filesystem;
41 
42 namespace rsc {
43 namespace plugins {
44 
45 Configurator::Configurator(ManagerPtr manager, const vector<path>& defaultPath)
46  : logger(logging::LoggerFactory::getInstance()
47  .getLogger("rsc.plugins.Configurator")),
48  manager(manager),
49  pathSet(false),
50  defaultPath(defaultPath) {
51 }
52 
54  // If a searchpath has not been set via configuration options, use
55  // the default.
56  if (!this->pathSet) {
57  RSCINFO(this->logger, "No searchpath configured; using default: "
58  << this->defaultPath);
60  }
61 
62  // Load all requested plugins.
63  for (set<string>::const_iterator it = this->load.begin();
64  it != this->load.end(); ++it) {
65  // Treat each element as a regular expression. Find matching
66  // plugins and load them. Note that regex syntax error can
67  // cause an exception here.
68  string pattern = *it;
69  RSCDEBUG(this->logger, "Looking up plugins matching pattern `"
70  << pattern << "'");
71  set<PluginPtr> matches;
72  try {
73  matches = this->manager->getPlugins(boost::regex(pattern));
74  } catch (const std::exception& e) {
75  throw runtime_error(str(format("Failed to lookup matching plugins for patterns `%1%' as requested via configuration: %2%")
76  % pattern
77  % e.what()));
78  }
79  RSCDEBUG(this->logger, "Found " << matches.size() << " match(es)");
80 
81  // Try to load all plugins matching the pattern.
82  for (set<PluginPtr>::iterator it = matches.begin();
83  it != matches.end(); ++it) {
84  RSCDEBUG(this->logger, "Loading plugin " << (*it)->getName());
85  try {
86  (*it)->load();
87  } catch (const std::exception& e) {
88  throw runtime_error(str(format("Failed to load plugin `%1%' as requested via configuration: %2%")
89  % (*it)->getName()
90  % e.what()));
91  }
92  }
93  }
94 }
95 
96 void Configurator::handleOption(const vector<string>& key,
97  const string& value) {
98  RSCDEBUG(this->logger, "Processing option " << key << " = `" << value << "'");
99 
100  // Ignore other options.
101  if (!((key.size() == 3)
102  && (key[0] == "plugins")
103  && (key[1] == "cpp"))) {
104  return;
105  }
106 
107  // Process plugins.cpp.{path,load} options.
108  if (key[2] == "path") {
109  // Split value at ":" tokens. Each substring is a searchpath
110  // entry.
111  vector<string> paths;
112 
113  try {
114  paths = splitValue(value);
115  } catch (const std::exception& e) {
116  throw invalid_argument(str(format("Invalid plugin load path (option %1%) value `%2%': %3%")
117  % boost::io::group(std::container_none,
118  std::element_sequence(".", ""),
119  key)
120  % value
121  % e.what()));
122  }
123 
124  // Add all specified paths. The empty string, produced by "::"
125  // means that the default searchpath should be spliced in.
126  for (vector<string>::const_iterator it = paths.begin();
127  it != paths.end(); ++it) {
128  string path = *it;
129  try {
130  if (path.empty()) {
131  path = "<default path>"; // for exception message
132  addDefaultPath();
133  } else {
134  this->manager->addPath(path);
135  }
136  } catch (const std::exception& e) {
137  throw runtime_error(str(format("Failed to add path `%1%' as requested via configuration: %2%")
138  % path
139  % e.what()));
140  }
141  }
142 
143  this->pathSet = true;
144  } else if (key[2] == "load") {
145  vector<string> names;
146 
147  try {
148  names = splitValue(value);
149  } catch (const std::exception& e) {
150  throw invalid_argument(str(format("Invalid list of plugins (option %1%) to load `%2%': %3%")
151  % boost::io::group(std::container_none,
152  std::element_sequence(".", ""),
153  key)
154  % value
155  % e.what()));
156  }
157 
158  copy(names.begin(), names.end(),
159  inserter(this->load, this->load.begin()));
160  } else {
161  throw invalid_argument(str(format("Invalid option key `%1%'; plugin related option keys are `path' and `load'.")
162  % boost::io::group(std::container_none,
163  std::element_sequence(".", ""),
164  key)));
165  }
166 }
167 
169  for (vector<path>::const_iterator it = this->defaultPath.begin();
170  it != this->defaultPath.end(); ++it) {
171  this->manager->addPath(*it);
172  }
173 }
174 
175 vector<string> Configurator::splitValue(const string& value) const {
176  vector<string> result;
177  boost::escaped_list_separator<char> sep('\\', ':');
178  boost::tokenizer< boost::escaped_list_separator<char> > tok(value, sep);
179  copy(tok.begin(), tok.end(), back_inserter(result));
180  return result;
181 }
182 
183 }
184 }
std::vector< boost::filesystem::path > defaultPath
Definition: Configurator.h:76
#define RSCDEBUG(logger, msg)
Definition: Logger.h:217
void handleOption(const std::vector< std::string > &key, const std::string &value)
This method is called once for each individual option available from a given ConfigSource.
std::set< std::string > load
Definition: Configurator.h:77
LoggerPtr getLogger()
#define RSCINFO(logger, msg)
Definition: Logger.h:224
std::vector< std::string > splitValue(const std::string &value) const
logging::LoggerPtr logger
Definition: Configurator.h:71
boost::shared_ptr< Manager > ManagerPtr
Definition: Manager.h:131