RSC  0.16.0
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, 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 "Configurator.h"
28 
29 #include <boost/format.hpp>
30 
31 #include <boost/tokenizer.hpp>
32 
33 #include "../runtime/ContainerIO.h"
34 #include "../runtime/NoSuchObject.h"
35 
36 #include "../config/Utility.h"
37 
38 #include "../logging/LoggerFactory.h"
39 
40 using namespace std;
41 
42 using namespace boost;
43 using namespace boost::filesystem;
44 
45 namespace rsc {
46 namespace plugins {
47 
48 Configurator::Configurator(ManagerPtr manager,
49  const vector<boost::filesystem::path>& defaultPath)
50  : logger(logging::LoggerFactory::getInstance()
51  .getLogger("rsc.plugins.Configurator")),
52  manager(manager),
53  defaultPath(defaultPath) {
54  // Gets interpreted as default path entries in execute().
55  this->path.push_back("");
56 }
57 
59 }
60 
61 void Configurator::execute(bool errorOnMissing) {
62  addPathEntries(this->path);
63  loadPlugins(this->load, errorOnMissing);
64 }
65 
66 void Configurator::handleOption(const vector<string>& key,
67  const string& value) {
68  RSCDEBUG(this->logger, "Processing option " << key << " = `" << value << "'");
69 
70  // Ignore other options.
71  if (!((key.size() == 3)
72  && (key[0] == "plugins")
73  && (key[1] == "cpp"))) {
74  return;
75  }
76 
77  // Process plugins.cpp.{path,load} options.
78  if (key[2] == "path") {
79  this->path = config::mergeSequenceValue("plugin load path",
80  key, value, this->path);
81  } else if (key[2] == "load") {
82  this->load = config::mergeSequenceValue("list of plugins to load",
83  key, value, this->load);
84  } else {
85  throw invalid_argument(str(format("Invalid option key `%1%'; plugin related option keys are `path' and `load'.")
86  % boost::io::group(std::container_none,
87  std::element_sequence(".", ""),
88  key)));
89  }
90 }
91 
93  for (vector<boost::filesystem::path>::const_iterator it = this->defaultPath.begin();
94  it != this->defaultPath.end(); ++it) {
95  this->manager->addPath(*it);
96  }
97 }
98 
99 void Configurator::addPathEntries(const vector<string>& entries) {
100  for (vector<string>::const_iterator it = entries.begin();
101  it != entries.end(); ++it) {
102  string path = *it;
103  try {
104  if (path.empty()) {
105  path = "<default path>"; // for exception message
106  RSCINFO(this->logger, "Adding default searchpath: "
107  << this->defaultPath);
108  addDefaultPath();
109  } else {
110  this->manager->addPath(path);
111  }
112  } catch (const std::exception& e) {
113  throw runtime_error(str(format("Failed to add path `%1%' as requested via configuration: %2%")
114  % path
115  % e.what()));
116  }
117  }
118 }
119 
120 void Configurator::loadPlugins(const vector<string>& names,
121  bool errorOnMissing) {
122  for (vector<string>::const_iterator it = names.begin();
123  it != names.end(); ++it) {
124  // Treat each element as a regular expression. Find matching
125  // plugins and load them. Note that regex syntax error can
126  // cause an exception here.
127  string pattern = *it;
128  RSCDEBUG(this->logger, "Looking up plugins matching pattern `"
129  << pattern << "'");
130  set<PluginPtr> matches;
131  try {
132  matches = this->manager->getPlugins(boost::regex(pattern));
133  } catch (const std::exception& e) {
134  throw runtime_error(str(format("Failed to lookup matching plugins for patterns `%1%' as requested via configuration: %2%")
135  % pattern
136  % e.what()));
137  }
138  RSCDEBUG(this->logger, "Found " << matches.size() << " match(es)");
139 
140  if (matches.empty() && errorOnMissing) {
141  throw runtime::NoSuchObject(str(format(
142  "Cannot find a plugin with name %1%") % pattern));
143  }
144 
145  // Try to load all plugins matching the pattern.
146  for (set<PluginPtr>::iterator it = matches.begin();
147  it != matches.end(); ++it) {
148  RSCDEBUG(this->logger, "Loading plugin " << (*it)->getName());
149  try {
150  (*it)->load();
151  } catch (const std::exception& e) {
152  throw runtime_error(str(format("Failed to load plugin `%1%' as requested via configuration: %2%")
153  % (*it)->getName()
154  % e.what()));
155  }
156  }
157  }
158 }
159 
160 }
161 }
std::vector< boost::filesystem::path > defaultPath
Definition: Configurator.h:84
#define RSCDEBUG(logger, msg)
Definition: Logger.h:217
detail::set_element_sequence_style< detail::element_sequence_style > element_sequence(const string &separator, const string &first_separator, const string &last_separator)
Definition: ContainerIO.cpp:98
STL namespace.
void loadPlugins(const std::vector< std::string > &names, bool errorOnMissing)
void execute(bool errorOnMissing=true)
Performs the actual loading of plugins.
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.
void addPathEntries(const std::vector< std::string > &entries)
LoggerPtr getLogger()
std::vector< std::string > path
Definition: Configurator.h:86
const detail::set_container_style< detail::container_style > container_none
#define RSCINFO(logger, msg)
Definition: Logger.h:224
vector< string > mergeSequenceValue(const string &description, const vector< string > &key, const string &raw, const vector< string > &previous)
Definition: Utility.cpp:47
std::vector< std::string > load
Definition: Configurator.h:87
logging::LoggerPtr logger
Definition: Configurator.h:80
boost::shared_ptr< Manager > ManagerPtr
Definition: Manager.h:131
This exception is thrown if a specified object does not exist.
Definition: NoSuchObject.h:43