class_loader  master
The class_loader package is a ROS-independent package for loading plugins during runtime.
multi_library_class_loader.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * * Neither the name of the copyright holders nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_
33 #define CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_
34 
35 #include <cstddef>
36 #include <map>
37 #include <memory>
38 #include <string>
39 #include <vector>
40 
41 // TODO(mikaelarguedas) remove this once console_bridge complies with this
42 // see https://github.com/ros/console_bridge/issues/55
43 #ifdef __clang__
44 # pragma clang diagnostic push
45 # pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
46 #endif
47 #include "console_bridge/console.h"
48 #ifdef __clang__
49 # pragma clang diagnostic pop
50 #endif
51 
54 
55 namespace class_loader
56 {
57 
61 
62 class MultiLibraryClassLoaderImpl;
63 
69 {
70 public:
76  explicit MultiLibraryClassLoader(bool enable_ondemand_loadunload);
77 
81  virtual ~MultiLibraryClassLoader();
82 
92  template<class Base>
94  {
95  CONSOLE_BRIDGE_logDebug(
96  "class_loader::MultiLibraryClassLoader: "
97  "Attempting to create instance of class type %s.",
98  class_name.c_str());
99  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
100  if (nullptr == loader) {
102  "MultiLibraryClassLoader: Could not create object of class type " +
103  class_name +
104  " as no factory exists for it. Make sure that the library exists and " +
105  "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
106  }
107 
108  return loader->createInstance<Base>(class_name);
109  }
110 
120  template<class Base>
122  const std::string & class_name, const std::string & library_path)
123  {
124  ClassLoader * loader = getClassLoaderForLibrary(library_path);
125  if (nullptr == loader) {
127  "Could not create instance as there is no ClassLoader in "
128  "MultiLibraryClassLoader bound to library " + library_path +
129  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
130  }
131  return loader->createInstance<Base>(class_name);
132  }
133 
135 
143  template<class Base>
145  {
146  CONSOLE_BRIDGE_logDebug(
147  "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.",
148  class_name.c_str());
149  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
150  if (nullptr == loader) {
152  "MultiLibraryClassLoader: Could not create object of class type " + class_name +
153  " as no factory exists for it. "
154  "Make sure that the library exists and was explicitly loaded through "
155  "MultiLibraryClassLoader::loadLibrary()");
156  }
157  return loader->createUniqueInstance<Base>(class_name);
158  }
159 
161 
169  template<class Base>
171  createUniqueInstance(const std::string & class_name, const std::string & library_path)
172  {
173  ClassLoader * loader = getClassLoaderForLibrary(library_path);
174  if (nullptr == loader) {
176  "Could not create instance as there is no ClassLoader in "
177  "MultiLibraryClassLoader bound to library " + library_path +
178  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
179  }
180  return loader->createUniqueInstance<Base>(class_name);
181  }
182 
193  template<class Base>
194  Base * createUnmanagedInstance(const std::string & class_name)
195  {
196  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
197  if (nullptr == loader) {
199  "MultiLibraryClassLoader: Could not create class of type " + class_name);
200  }
201  return loader->createUnmanagedInstance<Base>(class_name);
202  }
203 
213  template<class Base>
214  Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path)
215  {
216  ClassLoader * loader = getClassLoaderForLibrary(library_path);
217  if (nullptr == loader) {
219  "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader "
220  "bound to library " + library_path +
221  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
222  }
223  return loader->createUnmanagedInstance<Base>(class_name);
224  }
225 
233  template<class Base>
234  bool isClassAvailable(const std::string & class_name) const
235  {
236  std::vector<std::string> available_classes = getAvailableClasses<Base>();
237  return available_classes.end() != std::find(
238  available_classes.begin(), available_classes.end(), class_name);
239  }
240 
247  bool isLibraryAvailable(const std::string & library_path) const;
248 
255  template<class Base>
257  {
258  std::vector<std::string> available_classes;
259  for (auto & loader : getAllAvailableClassLoaders()) {
260  std::vector<std::string> loader_classes = loader->getAvailableClasses<Base>();
261  available_classes.insert(
262  available_classes.end(), loader_classes.begin(), loader_classes.end());
263  }
264  return available_classes;
265  }
266 
273  template<class Base>
275  {
276  ClassLoader * loader = getClassLoaderForLibrary(library_path);
277  if (nullptr == loader) {
279  "There is no ClassLoader in MultiLibraryClassLoader bound to library " +
280  library_path +
281  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
282  }
283  return loader->getAvailableClasses<Base>();
284  }
285 
291  std::vector<std::string> getRegisteredLibraries() const;
292 
298  void loadLibrary(const std::string & library_path);
299 
307  int unloadLibrary(const std::string & library_path);
308 
309 private:
316  bool isOnDemandLoadUnloadEnabled() const;
317 
324  ClassLoader * getClassLoaderForLibrary(const std::string & library_path);
325 
327 
331  template<typename Base>
332  ClassLoader * getClassLoaderForClass(const std::string & class_name)
333  {
334  ClassLoaderVector loaders = getAllAvailableClassLoaders();
335  for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) {
336  if (!(*i)->isLibraryLoaded()) {
337  (*i)->loadLibrary();
338  }
339  if ((*i)->isClassAvailable<Base>(class_name)) {
340  return *i;
341  }
342  }
343  return nullptr;
344  }
345 
351  ClassLoaderVector getAllAvailableClassLoaders() const;
352 
356  void shutdownAllClassLoaders();
357 
358  MultiLibraryClassLoaderImpl * impl_;
359 };
360 
361 
362 } // namespace class_loader
363 #endif // CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_
class_loader::impl::loadLibrary
void loadLibrary(const std::string &library_path, ClassLoader *loader)
Loads a library into memory if it has not already been done so. Attempting to load an already loaded ...
std::string
std::shared_ptr
class_loader
Definition: class_loader.hpp:59
class_loader::ClassLoader::createUnmanagedInstance
Base * createUnmanagedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Definition: class_loader.hpp:170
class_loader::MultiLibraryClassLoader::createUnmanagedInstance
Base * createUnmanagedInstance(const std::string &class_name)
Creates an instance of an object of given class name with ancestor class Base This version does not l...
Definition: multi_library_class_loader.hpp:194
std::vector
std::find
T find(T... args)
class_loader::MultiLibraryClassLoader
A ClassLoader that can bind more than one runtime library.
Definition: multi_library_class_loader.hpp:68
class_loader::ClassLoader::createInstance
std::shared_ptr< Base > createInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Definition: class_loader.hpp:125
class_loader::MultiLibraryClassLoader::createUnmanagedInstance
Base * createUnmanagedInstance(const std::string &class_name, const std::string &library_path)
Creates an instance of an object of given class name with ancestor class Base This version takes a sp...
Definition: multi_library_class_loader.hpp:214
class_loader::ClassLoader::getAvailableClasses
std::vector< std::string > getAvailableClasses() const
Indicates which classes (i.e. class_loader) that can be loaded by this object.
Definition: class_loader.hpp:110
class_loader::LibraryToClassLoaderMap
std::map< LibraryPath, class_loader::ClassLoader * > LibraryToClassLoaderMap
Definition: multi_library_class_loader.hpp:59
class_loader::MultiLibraryClassLoader::isClassAvailable
bool isClassAvailable(const std::string &class_name) const
Indicates if a class has been loaded and can be instantiated.
Definition: multi_library_class_loader.hpp:234
class_loader::MultiLibraryClassLoader::getAvailableClasses
std::vector< std::string > getAvailableClasses() const
Gets a list of all classes that are loaded by the class loader.
Definition: multi_library_class_loader.hpp:256
std::string::c_str
T c_str(T... args)
class_loader::ClassLoaderVector
std::vector< ClassLoader * > ClassLoaderVector
Definition: multi_library_class_loader.hpp:60
class_loader::MultiLibraryClassLoader::createUniqueInstance
ClassLoader::UniquePtr< Base > createUniqueInstance(const std::string &class_name, const std::string &library_path)
Creates an instance of an object of given class name with ancestor class Base.
Definition: multi_library_class_loader.hpp:171
class_loader::MultiLibraryClassLoader::createInstance
std::shared_ptr< Base > createInstance(const std::string &class_name, const std::string &library_path)
Creates an instance of an object of given class name with ancestor class Base This version takes a sp...
Definition: multi_library_class_loader.hpp:121
std::map
class_loader.hpp
class_loader::MultiLibraryClassLoader::getAvailableClassesForLibrary
std::vector< std::string > getAvailableClassesForLibrary(const std::string &library_path)
Gets a list of all classes loaded for a particular library.
Definition: multi_library_class_loader.hpp:274
class_loader::ClassLoader
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
Definition: class_loader.hpp:79
CLASS_LOADER_PUBLIC
#define CLASS_LOADER_PUBLIC
Definition: visibility_control.hpp:58
class_loader::ClassLoader::createUniqueInstance
UniquePtr< Base > createUniqueInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Definition: class_loader.hpp:147
std::vector::begin
T begin(T... args)
visibility_control.hpp
std::vector::insert
T insert(T... args)
class_loader::MultiLibraryClassLoader::createUniqueInstance
ClassLoader::UniquePtr< Base > createUniqueInstance(const std::string &class_name)
Creates an instance of an object of given class name with ancestor class Base.
Definition: multi_library_class_loader.hpp:144
class_loader::LibraryPath
std::string LibraryPath
Definition: multi_library_class_loader.hpp:58
std::vector::end
T end(T... args)
class_loader::MultiLibraryClassLoader::createInstance
std::shared_ptr< Base > createInstance(const std::string &class_name)
Creates an instance of an object of given class name with ancestor class Base This version does not l...
Definition: multi_library_class_loader.hpp:93
class_loader::NoClassLoaderExistsException
An exception class thrown when a multilibrary class loader does not have a ClassLoader bound to it.
Definition: exceptions.hpp:96
class_loader::impl::unloadLibrary
void unloadLibrary(const std::string &library_path, ClassLoader *loader)
Unloads a library if it loaded in memory and cleans up its corresponding class factories....
std::unique_ptr
class_loader::CreateClassException
An exception class thrown when class_loader is unable to create a plugin.
Definition: exceptions.hpp:83