RSC  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Configurator.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSB project.
4  *
5  * Copyright (C) 2012 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 (vector<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 = splitValue(value);
112 
113  // Add all specified paths. The empty string, produced by "::"
114  // means that the default searchpath should be spliced in.
115  for (vector<string>::const_iterator it = paths.begin();
116  it != paths.end(); ++it) {
117  string path = *it;
118  try {
119  if (path.empty()) {
120  path = "<default path>"; // for exception message
121  addDefaultPath();
122  } else {
123  this->manager->addPath(path);
124  }
125  } catch (const std::exception& e) {
126  throw runtime_error(str(format("Failed to add path `%1%' as requested via configuration: %2%")
127  % path
128  % e.what()));
129  }
130  }
131 
132  this->pathSet = true;
133  } else if (key[2] == "load") {
134  vector<string> temp = splitValue(value);
135  copy(temp.begin(), temp.end(), back_inserter(this->load));
136  } else {
137  throw invalid_argument(str(format("Invalid option key `%1%'; plugin related option keys are `path' and `load'.")
138  % key));
139  }
140 }
141 
143  for (vector<path>::const_iterator it = this->defaultPath.begin();
144  it != this->defaultPath.end(); ++it) {
145  this->manager->addPath(*it);
146  }
147 }
148 
149 vector<string> Configurator::splitValue(const string& value) const {
150  vector<string> result;
151  boost::escaped_list_separator<char> sep('\\', ':');
152  boost::tokenizer< boost::escaped_list_separator<char> > tok(value, sep);
153  copy(tok.begin(), tok.end(), back_inserter(result));
154  return result;
155 }
156 
157 }
158 }