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 <cstddef>
37 #include <map>
38 #include <string>
39 #include <vector>
40 
41 #include "console_bridge/console.h"
44 
45 namespace class_loader
46 {
47 
48 typedef std::string LibraryPath;
49 typedef std::map<LibraryPath, class_loader::ClassLoader *> LibraryToClassLoaderMap;
50 typedef std::vector<ClassLoader *> ClassLoaderVector;
51 
57 {
58 public:
63  explicit MultiLibraryClassLoader(bool enable_ondemand_loadunload);
64 
68  virtual ~MultiLibraryClassLoader();
69 
77  template<class Base>
78  std::shared_ptr<Base> createSharedInstance(const std::string & class_name)
79  {
80  CONSOLE_BRIDGE_logDebug(
81  "class_loader::MultiLibraryClassLoader: "
82  "Attempting to create instance of class type %s.",
83  class_name.c_str());
84  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
85  if (nullptr == loader) {
87  "MultiLibraryClassLoader: Could not create object of class type " +
88  class_name +
89  " as no factory exists for it. Make sure that the library exists and "
90  "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
91  }
92 
93  return loader->createSharedInstance<Base>(class_name);
94  }
95 
104  template<class Base>
105  std::shared_ptr<Base>
106  createSharedInstance(const std::string & class_name, const std::string & library_path)
107  {
108  ClassLoader * loader = getClassLoaderForLibrary(library_path);
109  if (nullptr == loader) {
111  "Could not create instance as there is no ClassLoader in "
112  "MultiLibraryClassLoader bound to library " + library_path +
113  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
114  }
115  return loader->createSharedInstance<Base>(class_name);
116  }
117 
122  template<class Base>
123  boost::shared_ptr<Base> createInstance(const std::string & class_name)
124  {
125  CONSOLE_BRIDGE_logDebug(
126  "class_loader::MultiLibraryClassLoader: "
127  "Attempting to create instance of class type %s.",
128  class_name.c_str());
129  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
130  if (nullptr == loader) {
132  "MultiLibraryClassLoader: Could not create object of class type " +
133  class_name +
134  " as no factory exists for it. Make sure that the library exists and "
135  "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
136  }
137 
138  return loader->createInstance<Base>(class_name);
139  }
140 
145  template<class Base>
146  boost::shared_ptr<Base>
147  createInstance(const std::string & class_name, const std::string & library_path)
148  {
149  ClassLoader * loader = getClassLoaderForLibrary(library_path);
150  if (nullptr == loader) {
152  "Could not create instance as there is no ClassLoader in "
153  "MultiLibraryClassLoader bound to library " + library_path +
154  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
155  }
156  return loader->createInstance<Base>(class_name);
157  }
158 
163  template<class Base>
164  ClassLoader::UniquePtr<Base> createUniqueInstance(const std::string & class_name)
165  {
166  CONSOLE_BRIDGE_logDebug(
167  "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.",
168  class_name.c_str());
169  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
170  if (nullptr == loader) {
172  "MultiLibraryClassLoader: Could not create object of class type " + class_name +
173  " as no factory exists for it. "
174  "Make sure that the library exists and was explicitly loaded through "
175  "MultiLibraryClassLoader::loadLibrary()");
176  }
177  return loader->createUniqueInstance<Base>(class_name);
178  }
179 
184  template<class Base>
186  createUniqueInstance(const std::string & class_name, const std::string & library_path)
187  {
188  ClassLoader * loader = getClassLoaderForLibrary(library_path);
189  if (nullptr == loader) {
191  "Could not create instance as there is no ClassLoader in "
192  "MultiLibraryClassLoader bound to library " + library_path +
193  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
194  }
195  return loader->createUniqueInstance<Base>(class_name);
196  }
197 
206  template<class Base>
207  Base * createUnmanagedInstance(const std::string & class_name)
208  {
209  ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
210  if (nullptr == loader) {
212  "MultiLibraryClassLoader: Could not create class of type " + class_name);
213  }
214  return loader->createUnmanagedInstance<Base>(class_name);
215  }
216 
225  template<class Base>
226  Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path)
227  {
228  ClassLoader * loader = getClassLoaderForLibrary(library_path);
229  if (nullptr == loader) {
231  "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader "
232  "bound to library " + library_path +
233  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
234  }
235  return loader->createUnmanagedInstance<Base>(class_name);
236  }
237 
244  template<class Base>
245  bool isClassAvailable(const std::string & class_name)
246  {
247  std::vector<std::string> available_classes = getAvailableClasses<Base>();
248  return available_classes.end() != std::find(
249  available_classes.begin(), available_classes.end(), class_name);
250  }
251 
257  bool isLibraryAvailable(const std::string & library_path);
258 
264  template<class Base>
265  std::vector<std::string> getAvailableClasses()
266  {
267  std::vector<std::string> available_classes;
268  for (auto & loader : getAllAvailableClassLoaders()) {
269  std::vector<std::string> loader_classes = loader->getAvailableClasses<Base>();
270  available_classes.insert(
271  available_classes.end(), loader_classes.begin(), loader_classes.end());
272  }
273  return available_classes;
274  }
275 
281  template<class Base>
282  std::vector<std::string> getAvailableClassesForLibrary(const std::string & library_path)
283  {
284  ClassLoader * loader = getClassLoaderForLibrary(library_path);
285  if (nullptr == loader) {
287  "There is no ClassLoader in MultiLibraryClassLoader bound to library " +
288  library_path +
289  " Ensure you called MultiLibraryClassLoader::loadLibrary()");
290  }
291  return loader->getAvailableClasses<Base>();
292  }
293 
298  std::vector<std::string> getRegisteredLibraries();
299 
304  void loadLibrary(const std::string & library_path);
305 
310  int unloadLibrary(const std::string & library_path);
311 
312 private:
316  bool isOnDemandLoadUnloadEnabled() {return enable_ondemand_loadunload_;}
317 
323  ClassLoader * getClassLoaderForLibrary(const std::string & library_path);
324 
330  template<typename Base>
331  ClassLoader * getClassLoaderForClass(const std::string & class_name)
332  {
333  ClassLoaderVector loaders = getAllAvailableClassLoaders();
334  for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) {
335  if (!(*i)->isLibraryLoaded()) {
336  (*i)->loadLibrary();
337  }
338  if ((*i)->isClassAvailable<Base>(class_name)) {
339  return *i;
340  }
341  }
342  return nullptr;
343  }
344 
348  ClassLoaderVector getAllAvailableClassLoaders();
349 
353  void shutdownAllClassLoaders();
354 
355 private:
357  LibraryToClassLoaderMap active_class_loaders_;
358  boost::mutex loader_mutex_;
359 };
360 
361 
362 } // namespace class_loader
363 #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::UniquePtr< Base > createUniqueInstance(const std::string &class_name)
Creates an instance of an object of given class name with ancestor class Base Same as createSharedIns...
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.
CLASS_LOADER_PUBLIC 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::vector< std::string > getAvailableClassesForLibrary(const std::string &library_path)
Gets a list of all classes loaded for a particular library.
UniquePtr< Base > createUniqueInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Base * createUnmanagedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
std::shared_ptr< Base > createSharedInstance(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...
std::vector< std::string > getAvailableClasses()
Gets a list of all classes that are loaded by the class loader.
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 Same as createSharedIns...
CLASS_LOADER_PUBLIC void unloadLibrary(const std::string &library_path, ClassLoader *loader)
Unloads a library if it loaded in memory and cleans up its corresponding class factories. If it is not loaded, the function has no effect.
An exception class thrown when class_loader is unable to create a plugin.
Definition: exceptions.hpp:81
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
std::vector< ClassLoader * > ClassLoaderVector
std::shared_ptr< Base > createSharedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
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...
std::shared_ptr< Base > createSharedInstance(const std::string &class_name)
Creates an instance of an object of given class name with ancestor class Base This version does not l...
An exception class thrown when a multilibrary class loader does not have a ClassLoader bound to it...
Definition: exceptions.hpp:93
std::map< LibraryPath, class_loader::ClassLoader * > LibraryToClassLoaderMap
std::unique_ptr< Base, DeleterType< Base > > UniquePtr
#define CLASS_LOADER_PUBLIC
boost::shared_ptr< Base > createInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
bool isOnDemandLoadUnloadEnabled()
Indicates if on-demand (lazy) load/unload is enabled so libraries are loaded/unloaded automatically a...
boost::shared_ptr< Base > createInstance(const std::string &class_name)
Creates an instance of an object of given class name with ancestor class Base Same as createSharedIns...
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 Same as createSharedIns...


class_loader
Author(s): Mirza Shah, Steven! Ragnarök
autogenerated on Mon Feb 28 2022 22:02:03