RSC  0.16.0
Manager.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 "Manager.h"
28 
29 #include <stdexcept>
30 #include <algorithm>
31 
32 #include <boost/filesystem/operations.hpp>
33 #include <boost/regex.hpp>
34 #include <boost/format.hpp>
35 
36 #include "../runtime/NoSuchObject.h"
37 #include "../logging/LoggerFactory.h"
38 
39 using namespace std;
40 
41 using namespace boost;
42 using namespace boost::filesystem;
43 
44 namespace rsc {
45 namespace plugins {
46 
47 Manager::Manager()
48  : logger(logging::LoggerFactory::getInstance()
49  .getLogger("rsc.plugins.Manager")) {
50 }
51 
53 }
54 
55 vector<path> Manager::getPath() const {
56  return this->path;
57 }
58 
59 void Manager::addPath(const boost::filesystem::path& path) {
60  // Ignore duplicates.
61  if (find(this->path.begin(), this->path.end(), path)
62  != this->path.end()) {
63  return;
64  }
65 
66  // Search specified directory for plugins.
67  RSCINFO(this->logger, "Adding path " << path);
68  this->path.push_back(path);
69  if (!is_directory(path)) {
70  RSCINFO(this->logger, "Ignoring non-existent path `" << path << "'");
71  return;
72  }
73 
74  set<string> namesInThisPath;
75  for (directory_iterator it = directory_iterator(path);
76  it != directory_iterator(); ++it) {
77  RSCTRACE(this->logger, "Processing " << it->path());
78  if (!is_regular_file(it->path())) {
79  RSCINFO(this->logger, "Ignoring non-regular file " << it->path());
80  continue;
81  }
82 
83  // Extract the plugin name from the library name.
84  string name = it->path()
85 #if BOOST_FILESYSTEM_VERSION == 3
86  .filename().string();
87 #else
88  .filename();
89 #endif
90  // Strip leading "lib" and trailing ".so*", ".dylib*", etc
91  regex libraryName (
92 #if defined(__linux__)
93  "^lib([^.]*)(.*)\\.so(.*)$"
94 #elif defined(__APPLE__)
95  "^lib([^.]*)(.*)\\.dylib$"
96 #elif defined(_WIN32)
97  "^([^.]*)(.*)\\.dll$"
98 #else
99  ""
100 #endif
101  );
102  if (!regex_match(name, libraryName)) {
103  RSCINFO(this->logger, "Ignoring non-matching file " << name);
104  continue;
105  }
106 
107  name = regex_replace(name, libraryName, "\\1");
108  if (namesInThisPath.count(name) != 0) {
109  throw runtime_error(
110  boost::str(
111  boost::format(
112  "The path %1% contains multiple plugins forming the plugin name %2%.")
113  % path % name));
114  }
115  namesInThisPath.insert(name);
116 
117  boost::filesystem::path library = it->path();
118 
119  // If there is not yet an entry for the given name, add a
120  // new plugin entry. Otherwise, ignore the plugin. This
121  // logic implements precedence of searchpath entries.
122  RSCINFO(this->logger, "Found plugin `"
123  << name << "' [" << library << "]");
124  if (this->plugins.find(name) == this->plugins.end()) {
125  this->plugins[name]
126  = Plugin::create(name, library.string());
127  }
128  }
129 }
130 
131 set<PluginPtr> Manager::getPlugins(const boost::regex& regex) const {
132  set<PluginPtr> result;
133 
134  for (PluginMap::const_iterator it = this->plugins.begin();
135  it != this->plugins.end(); ++it) {
136  if (regex_match(it->first, regex)) {
137  result.insert(it->second);
138  }
139  }
140  return result;
141  }
142 
143 set<PluginPtr> Manager::getPlugins(const string& regex) const {
144  return getPlugins(boost::regex(regex));
145 }
146 
147 PluginPtr Manager::getPlugin(const string& name) const {
148  PluginMap::const_iterator it;
149  if ((it = this->plugins.find(name)) == this->plugins.end()) {
150  throw runtime::NoSuchObject(name);
151  }
152  return it->second;
153 }
154 
155 }
156 }
STL namespace.
void addPath(const boost::filesystem::path &path)
Adds path to the list of search path entries.
Definition: Manager.cpp:59
virtual ~Manager()
Definition: Manager.cpp:52
std::vector< boost::filesystem::path > getPath() const
Returns the current plugin search path.
Definition: Manager.cpp:55
static boost::shared_ptr< Plugin > create(const std::string &name, const std::string &library)
Definition: Plugin.cpp:231
LoggerPtr getLogger()
#define RSCTRACE(logger, msg)
Definition: Logger.h:210
#define RSCINFO(logger, msg)
Definition: Logger.h:224
boost::shared_ptr< Plugin > PluginPtr
Definition: Plugin.h:106
PluginMap plugins
Definition: Manager.h:127
std::set< PluginPtr > getPlugins(const boost::regex &regex=boost::regex(".*")) const
Returns the set of known plugins, potentially filtered by name according to regular expression regex...
Definition: Manager.cpp:131
PluginPtr getPlugin(const std::string &name) const
Return the plugin designated by name.
Definition: Manager.cpp:147
logging::LoggerPtr logger
Definition: Manager.h:124
This exception is thrown if a specified object does not exist.
Definition: NoSuchObject.h:43