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 <boost/thread.hpp>
36 #include <map>
37 #include <string>
38 #include <vector>
39 
40 #include "console_bridge/console.h"
41 
44 
45 // TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release
46 
47 namespace class_loader
48 {
49 
50 typedef std::string LibraryPath;
51 typedef std::map<LibraryPath, class_loader::ClassLoader *> LibraryToClassLoaderMap;
52 typedef std::vector<ClassLoader *> ClassLoaderVector;
53 
59 {
60 public:
65  MultiLibraryClassLoader(bool enable_ondemand_loadunload); // NOLINT(runtime/explicit)
66 
70  virtual ~MultiLibraryClassLoader();
71 
79  template<class Base>
80  boost::shared_ptr<Base> createInstance(const std::string & class_name)
81  {
83  "class_loader::MultiLibraryClassLoader: "
84  "Attempting to create instance of class type %s.",
85  class_name.c_str());
86  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
87  if (NULL == loader) {
89  "MultiLibraryClassLoader: Could not create object of class type " +
90  class_name +
91  " as no factory exists for it. Make sure that the library exists and "
92  "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
93  }
94 
95  return loader->createInstance<Base>(class_name);
96  }
97 
106  template<class Base>
107  boost::shared_ptr<Base>
108  createInstance(const std::string & class_name, const std::string & library_path)
109  {
110  ClassLoader * loader = getClassLoaderForLibrary(library_path);
111  if (NULL == loader) {
113  "Could not create instance as there is no ClassLoader in "
114  "MultiLibraryClassLoader bound to library " + library_path +
115  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
116  }
117  return loader->createInstance<Base>(class_name);
118  }
119 
120 #if __cplusplus >= 201103L
121 
128  template<class Base>
129  ClassLoader::UniquePtr<Base> createUniqueInstance(const std::string & class_name)
130  {
132  "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.",
133  class_name.c_str());
134  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
135  if (nullptr == loader) {
137  "MultiLibraryClassLoader: Could not create object of class type " + class_name +
138  " as no factory exists for it. "
139  "Make sure that the library exists and was explicitly loaded through "
140  "MultiLibraryClassLoader::loadLibrary()");
141  }
142  return loader->createUniqueInstance<Base>(class_name);
143  }
144 
153  template<class Base>
154  ClassLoader::UniquePtr<Base>
155  createUniqueInstance(const std::string & class_name, const std::string & library_path)
156  {
157  ClassLoader * loader = getClassLoaderForLibrary(library_path);
158  if (nullptr == loader) {
160  "Could not create instance as there is no ClassLoader in "
161  "MultiLibraryClassLoader bound to library " + library_path +
162  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
163  }
164  return loader->createUniqueInstance<Base>(class_name);
165  }
166 #endif
167 
176  template<class Base>
177  Base * createUnmanagedInstance(const std::string & class_name)
178  {
179  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
180  if (NULL == loader) {
182  "MultiLibraryClassLoader: Could not create class of type " + class_name);
183  }
184  return loader->createUnmanagedInstance<Base>(class_name);
185  }
186 
195  template<class Base>
196  Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path)
197  {
198  ClassLoader * loader = getClassLoaderForLibrary(library_path);
199  if (NULL == loader) {
201  "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader "
202  "bound to library " + library_path +
203  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
204  }
205  return loader->createUnmanagedInstance<Base>(class_name);
206  }
207 
214  template<class Base>
215  bool isClassAvailable(const std::string & class_name)
216  {
217  std::vector<std::string> available_classes = getAvailableClasses<Base>();
218  return available_classes.end() != std::find(
219  available_classes.begin(), available_classes.end(), class_name);
220  }
221 
227  bool isLibraryAvailable(const std::string & library_path);
228 
234  template<class Base>
235  std::vector<std::string> getAvailableClasses()
236  {
237  std::vector<std::string> available_classes;
238  ClassLoaderVector loaders = getAllAvailableClassLoaders();
239  for (unsigned int c = 0; c < loaders.size(); c++) {
240  ClassLoader * current = loaders.at(c);
241  std::vector<std::string> loader_classes = current->getAvailableClasses<Base>();
242  available_classes.insert(
243  available_classes.end(), loader_classes.begin(), loader_classes.end());
244  }
245  return available_classes;
246  }
247 
253  template<class Base>
254  std::vector<std::string> getAvailableClassesForLibrary(const std::string & library_path)
255  {
256  ClassLoader * loader = getClassLoaderForLibrary(library_path);
257  std::vector<std::string> available_classes;
258  if (loader) {
259  available_classes = loader->getAvailableClasses<Base>();
260  return available_classes;
261  } else {
263  "There is no ClassLoader in MultiLibraryClassLoader bound to library " +
264  library_path +
265  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
266  }
267  }
268 
273  std::vector<std::string> getRegisteredLibraries();
274 
279  void loadLibrary(const std::string & library_path);
280 
285  int unloadLibrary(const std::string & library_path);
286 
287 private:
292 
298  ClassLoader * getClassLoaderForLibrary(const std::string & library_path);
299 
305  template<typename Base>
306  ClassLoader * getClassLoaderForClass(const std::string & class_name)
307  {
308  ClassLoaderVector loaders = getAllAvailableClassLoaders();
309  for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) {
310  if (!(*i)->isLibraryLoaded()) {
311  (*i)->loadLibrary();
312  }
313  if ((*i)->isClassAvailable<Base>(class_name)) {
314  return *i;
315  }
316  }
317  return NULL;
318  }
319 
323  ClassLoaderVector getAllAvailableClassLoaders();
324 
329 
330 private:
332  LibraryToClassLoaderMap active_class_loaders_;
333  boost::mutex loader_mutex_;
334 };
335 
336 
337 } // namespace class_loader
338 #endif // CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_
Definition: base.hpp:33
std::vector< std::string > getAvailableClasses()
Indicates which classes (i.e. class_loader) that can be loaded by this object.
ClassLoader * getClassLoaderForClass(const std::string &class_name)
Gets a handle to the class loader corresponding to a specific class.
A ClassLoader that can bind more than one runtime library.
std::vector< std::string > getAvailableClassesForLibrary(const std::string &library_path)
Gets a list of all classes loaded for a particular library.
bool isLibraryAvailable(const std::string &library_path)
Indicates if a library has been loaded into memory.
Base * createUnmanagedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
std::vector< std::string > getAvailableClasses()
Gets a list of all classes that are loaded by the class loader.
int unloadLibrary(const std::string &library_path)
Unloads a library for this class loader.
#define CONSOLE_BRIDGE_logDebug(fmt,...)
An exception class thrown when class_loader is unable to create a plugin.
Definition: exceptions.hpp:80
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
std::vector< ClassLoader * > ClassLoaderVector
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...
void loadLibrary(const std::string &library_path)
Loads a library into memory for this class loader.
An exception class thrown when a multilibrary class loader does not have a ClassLoader bound to it...
Definition: exceptions.hpp:91
void shutdownAllClassLoaders()
Destroys all ClassLoaders.
std::map< LibraryPath, class_loader::ClassLoader * > LibraryToClassLoaderMap
virtual ~MultiLibraryClassLoader()
Virtual destructor for class.
std::vector< std::string > getRegisteredLibraries()
Gets a list of all libraries opened by this class loader .
MultiLibraryClassLoader(bool enable_ondemand_loadunload)
Constructor for the class.
boost::shared_ptr< Base > createInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
ClassLoaderVector getAllAvailableClassLoaders()
Gets all class loaders loaded within scope.
bool isOnDemandLoadUnloadEnabled()
Indicates if on-demand (lazy) load/unload is enabled so libraries are loaded/unloaded automatically a...
ClassLoader * getClassLoaderForLibrary(const std::string &library_path)
Gets a handle to the class loader corresponding to a specific runtime library.
boost::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...
bool isClassAvailable(const std::string &class_name)
Indicates if a class has been loaded and can be instantiated.
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...
boost::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...


class_loader
Author(s): Mirza Shah
autogenerated on Mon Jun 10 2019 12:51:50