Tesseract
Motion Planning Environment
Loading...
Searching...
No Matches
plugin_loader.hpp
Go to the documentation of this file.
1
26#ifndef TESSERACT_COMMON_PLUGIN_LOADER_HPP
27#define TESSERACT_COMMON_PLUGIN_LOADER_HPP
28
31#include <boost/algorithm/string.hpp>
32#include <console_bridge/console.h>
33#include <ostream>
35
38
39namespace tesseract_common
40{
41inline std::set<std::string> parseEnvironmentVariableList(const std::string& env_variable)
42{
43 std::set<std::string> list;
44 char* env_var = std::getenv(env_variable.c_str());
45 if (env_var == nullptr) // Environment variable not found
46 return list;
47
48 std::string evn_str = std::string(env_var);
49#ifndef _WIN32
50 boost::split(list, evn_str, boost::is_any_of(":"), boost::token_compress_on);
51#else
52 boost::split(list, evn_str, boost::is_any_of(";"), boost::token_compress_on);
53#endif
54 return list;
55}
56
57inline std::set<std::string> getAllSearchPaths(const std::string& search_paths_env,
58 const std::set<std::string>& existing_search_paths)
59{
60 // Check for environment variable to override default library
61 if (!search_paths_env.empty())
62 {
63 std::set<std::string> search_paths = parseEnvironmentVariableList(search_paths_env);
64 search_paths.insert(existing_search_paths.begin(), existing_search_paths.end());
65 return search_paths;
66 }
67
68 return existing_search_paths;
69}
70
71inline std::set<std::string> getAllSearchLibraries(const std::string& search_libraries_env,
72 const std::set<std::string>& existing_search_libraries)
73{
74 // Check for environment variable to override default library
75 if (!search_libraries_env.empty())
76 {
77 std::set<std::string> search_libraries = parseEnvironmentVariableList(search_libraries_env);
78 search_libraries.insert(existing_search_libraries.begin(), existing_search_libraries.end());
79 return search_libraries;
80 }
81
82 return existing_search_libraries;
83}
84
90inline std::set<std::string> extractLibrariesWithFullPath(std::set<std::string>& library_names)
91{
92 std::set<std::string> libraries_with_fullpath;
93 for (auto it = library_names.begin(); it != library_names.end();)
94 {
95 if (boost::filesystem::exists(*it) && boost::filesystem::path(*it).is_absolute())
96 {
97 libraries_with_fullpath.insert(*it);
98 it = library_names.erase(it);
99 }
100 else
101 {
102 ++it;
103 }
104 }
105
106 return libraries_with_fullpath;
107}
108
109template <class PluginBase>
110std::shared_ptr<PluginBase> PluginLoader::instantiate(const std::string& plugin_name) const
111{
112 // Check for environment variable for plugin definitions
113 std::set<std::string> library_names = getAllSearchLibraries(search_libraries_env, search_libraries);
114 if (library_names.empty())
115 {
116 CONSOLE_BRIDGE_logError("No plugin libraries were provided!");
117 return nullptr;
118 }
119
120 std::set<std::string> libraries_with_fullpath = extractLibrariesWithFullPath(library_names);
121 for (const auto& library_fullpath : libraries_with_fullpath)
122 {
123 if (ClassLoader::isClassAvailable(plugin_name, library_fullpath))
124 return ClassLoader::createSharedInstance<PluginBase>(plugin_name, library_fullpath);
125 }
126
127 // Check for environment variable for search paths
128 std::set<std::string> search_paths_local = getAllSearchPaths(search_paths_env, search_paths);
129 for (const auto& path : search_paths_local)
130 {
131 for (const auto& library : search_libraries)
132 {
133 if (ClassLoader::isClassAvailable(plugin_name, library, path))
134 return ClassLoader::createSharedInstance<PluginBase>(plugin_name, library, path);
135 }
136 }
137
138 // If not found in any of the provided search paths then search system folders if allowed
140 {
141 for (const auto& library : search_libraries)
142 {
143 if (ClassLoader::isClassAvailable(plugin_name, library))
144 return ClassLoader::createSharedInstance<PluginBase>(plugin_name, library);
145 }
146 }
147
148 std::stringstream msg;
150 msg << std::endl << "Search Paths (Search System Folders: True):" << std::endl;
151 else
152 msg << std::endl << "Search Paths (Search System Folders: False):" << std::endl;
153
154 for (const auto& path : search_paths_local)
155 msg << " - " + path << std::endl;
156
157 msg << "Search Libraries:" << std::endl;
158 for (const auto& library : search_libraries)
159 msg << " - " + ClassLoader::decorate(library) << std::endl;
160
161 CONSOLE_BRIDGE_logError("Failed to instantiate plugin '%s', Details: %s", plugin_name.c_str(), msg.str().c_str());
162
163 return nullptr;
164}
165
166bool PluginLoader::isPluginAvailable(const std::string& plugin_name) const
167{
168 // Check for environment variable for plugin definitions
169 std::set<std::string> library_names = getAllSearchLibraries(search_libraries_env, search_libraries);
170 if (library_names.empty())
171 {
172 CONSOLE_BRIDGE_logError("No plugin libraries were provided!");
173 return false;
174 }
175
176 // Check for libraries provided as full paths. These are searched first
177 std::set<std::string> libraries_with_fullpath = extractLibrariesWithFullPath(library_names);
178 for (const auto& library_fullpath : libraries_with_fullpath)
179 {
180 if (ClassLoader::isClassAvailable(plugin_name, library_fullpath))
181 return true;
182 }
183
184 // Check for environment variable to override default library
185 std::set<std::string> search_paths_local = getAllSearchPaths(search_paths_env, search_paths);
186 for (const auto& path : search_paths_local)
187 {
188 for (const auto& library : search_libraries)
189 {
190 if (ClassLoader::isClassAvailable(plugin_name, library, path))
191 return true;
192 }
193 }
194
195 // If not found in any of the provided search paths then search system folders if allowed
197 {
198 for (const auto& library : search_libraries)
199 {
200 if (ClassLoader::isClassAvailable(plugin_name, library))
201 return true;
202 }
203 }
204
205 return false;
206}
207
208template <class PluginBase>
209std::vector<std::string> PluginLoader::getAvailablePlugins() const
210{
211 return getAvailablePlugins(PluginBase::SECTION_NAME);
212}
213
214std::vector<std::string> PluginLoader::getAvailablePlugins(const std::string& section) const
215{
216 std::vector<std::string> plugins;
217
218 // Check for environment variable for plugin definitions
219 std::set<std::string> library_names = getAllSearchLibraries(search_libraries_env, search_libraries);
220 if (library_names.empty())
221 {
222 CONSOLE_BRIDGE_logError("No plugin libraries were provided!");
223 return plugins;
224 }
225
226 // Check for libraries provided as full paths. These are searched first
227 std::set<std::string> libraries_with_fullpath = extractLibrariesWithFullPath(library_names);
228 for (const auto& library_fullpath : libraries_with_fullpath)
229 {
230 std::vector<std::string> lib_plugins = ClassLoader::getAvailableSymbols(section, library_fullpath);
231 plugins.insert(plugins.end(), lib_plugins.begin(), lib_plugins.end());
232 }
233
234 // Check for environment variable to override default library
235 std::set<std::string> search_paths_local = getAllSearchPaths(search_paths_env, search_paths);
236 for (const auto& path : search_paths_local)
237 {
238 for (const auto& library : search_libraries)
239 {
240 std::vector<std::string> lib_plugins = ClassLoader::getAvailableSymbols(section, library, path);
241 plugins.insert(plugins.end(), lib_plugins.begin(), lib_plugins.end());
242 }
243 }
244
245 return plugins;
246}
247
248std::vector<std::string> PluginLoader::getAvailableSections(bool include_hidden) const
249{
250 std::vector<std::string> sections;
251
252 // Check for environment variable for plugin definitions
253 std::set<std::string> library_names = getAllSearchLibraries(search_libraries_env, search_libraries);
254 if (library_names.empty())
255 {
256 CONSOLE_BRIDGE_logError("No plugin libraries were provided!");
257 return sections;
258 }
259
260 // Check for libraries provided as full paths. These are searched first
261 std::set<std::string> libraries_with_fullpath = extractLibrariesWithFullPath(library_names);
262 for (const auto& library_fullpath : libraries_with_fullpath)
263 {
264 std::vector<std::string> lib_sections = ClassLoader::getAvailableSections(library_fullpath, "", include_hidden);
265 sections.insert(sections.end(), lib_sections.begin(), lib_sections.end());
266 }
267
268 // Check for environment variable to override default library
269 std::set<std::string> search_paths_local = getAllSearchPaths(search_paths_env, search_paths);
270 for (const auto& path : search_paths_local)
271 {
272 for (const auto& library : search_libraries)
273 {
274 std::vector<std::string> lib_sections = ClassLoader::getAvailableSections(library, path, include_hidden);
275 sections.insert(sections.end(), lib_sections.begin(), lib_sections.end());
276 }
277 }
278
279 return sections;
280}
281
283{
284 return static_cast<int>(getAllSearchLibraries(search_libraries_env, search_libraries).size());
285}
286
287void PluginLoader::addSymbolLibraryToSearchLibrariesEnv(const void* symbol_ptr, const std::string& search_libraries_env)
288{
289 std::string env_var_str;
290 char* env_var = std::getenv(search_libraries_env.c_str());
291 if (env_var != nullptr)
292 {
293 env_var_str = env_var;
294 }
295
296 boost::filesystem::path lib_path = boost::filesystem::canonical(boost::dll::symbol_location_ptr(symbol_ptr));
297
298 if (env_var_str.empty())
299 {
300 env_var_str = lib_path.string();
301 }
302 else
303 {
304#ifndef _WIN32
305 env_var_str = env_var_str + ":" + lib_path.string();
306#else
307 env_var_str = env_var_str + ";" + lib_path.string();
308#endif
309 }
310
311#ifndef _WIN32
312 setenv(search_libraries_env.c_str(), env_var_str.c_str(), 1);
313#else
314 _putenv_s(search_libraries_env.c_str(), env_var_str.c_str());
315#endif
316}
317
318} // namespace tesseract_common
319
320#endif // TESSERACT_COMMON_PLUGIN_LOADER_HPP
Class Loader to be used throughout Tesseract for loading plugins.
static void addSymbolLibraryToSearchLibrariesEnv(const void *symbol_ptr, const std::string &search_libraries_env)
Utility function to add library containing symbol to the search env variable.
Definition: plugin_loader.hpp:287
std::set< std::string > search_paths
A list of paths to search for plugins.
Definition: plugin_loader.h:63
std::string search_paths_env
The environment variable containing plugin search paths.
Definition: plugin_loader.h:69
std::shared_ptr< PluginBase > instantiate(const std::string &plugin_name) const
Instantiate a plugin with the provided name.
Definition: plugin_loader.hpp:110
std::vector< std::string > getAvailableSections(bool include_hidden=false) const
Get the available sections within the provided search libraries.
Definition: plugin_loader.hpp:248
int count() const
The number of plugins stored. The size of plugins variable.
Definition: plugin_loader.hpp:282
std::set< std::string > search_libraries
A list of library names without the prefix or suffix that contain plugins.
Definition: plugin_loader.h:66
bool isPluginAvailable(const std::string &plugin_name) const
Check if plugin is available.
Definition: plugin_loader.hpp:166
std::vector< std::string > getAvailablePlugins() const
Get the available plugins for the provided PluginBase type.
Definition: plugin_loader.hpp:209
std::string search_libraries_env
The environment variable containing plugins.
Definition: plugin_loader.h:77
bool search_system_folders
Indicate is system folders may be search if plugin is not found in any of the paths.
Definition: plugin_loader.h:60
auto it
Definition: collision_core_unit.cpp:208
const YAML::Node & search_paths
Definition: contact_managers_factory_unit.cpp:157
const YAML::Node & search_libraries
Definition: contact_managers_factory_unit.cpp:158
Common Tesseract Macros.
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
Definition: macros.h:71
Definition: create_convex_hull.cpp:36
Definition: allowed_collision_matrix.h:16
std::set< std::string > getAllSearchPaths(const std::string &search_paths_env, const std::set< std::string > &existing_search_paths)
Definition: plugin_loader.hpp:57
std::set< std::string > getAllSearchLibraries(const std::string &search_libraries_env, const std::set< std::string > &existing_search_libraries)
Definition: plugin_loader.hpp:71
std::set< std::string > extractLibrariesWithFullPath(std::set< std::string > &library_names)
This will remove libraries with full path in the provided library_names and return them.
Definition: plugin_loader.hpp:90
std::set< std::string > parseEnvironmentVariableList(const std::string &env_variable)
Definition: plugin_loader.hpp:41
Plugin Loader to be used throughout Tesseract for loading plugins.
sections
Definition: plugin_loader_unit.cpp:65
std::string env_var
Definition: resource_locator_unit.cpp:95
static bool isClassAvailable(const std::string &symbol_name, const std::string &library_name, const std::string &library_directory="")
Check if the symbol is available in the library_name searching system folders for library.
Definition: class_loader.hpp:82
static std::vector< std::string > getAvailableSections(const std::string &library_name, const std::string &library_directory="", bool include_hidden=false)
Get a list of available sections.
Definition: class_loader.hpp:148
static std::vector< std::string > getAvailableSymbols(const std::string &section, const std::string &library_name, const std::string &library_directory="")
Get a list of available symbols under the provided section.
Definition: class_loader.hpp:113
static std::string decorate(const std::string &library_name, const std::string &library_directory="")
Give library name without prefix and suffix it will return the library name with the prefix and suffi...
Definition: class_loader.hpp:196
object discrete_plugin_infos plugins["plugin_key"]
Definition: tesseract_common_serialization_unit.cpp:148
tesseract_common::fs::path path
Definition: tesseract_srdf_unit.cpp:1992