multi_library_class_loader.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright (c) 2012, Willow Garage, Inc.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the copyright holders nor the names of its
00016  *       contributors may be used to endorse or promote products derived from
00017  *       this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #ifndef CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_
00033 #define CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_
00034 
00035 #include <boost/thread.hpp>
00036 #include <map>
00037 #include <string>
00038 #include <vector>
00039 
00040 #include "console_bridge/console.h"
00041 
00042 #include "class_loader/class_loader.hpp"
00043 #include "class_loader/console_bridge_compatibility.hpp"
00044 
00045 // TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release
00046 
00047 namespace class_loader
00048 {
00049 
00050 typedef std::string LibraryPath;
00051 typedef std::map<LibraryPath, class_loader::ClassLoader *> LibraryToClassLoaderMap;
00052 typedef std::vector<ClassLoader *> ClassLoaderVector;
00053 
00058 class MultiLibraryClassLoader
00059 {
00060 public:
00065   MultiLibraryClassLoader(bool enable_ondemand_loadunload);  // NOLINT(runtime/explicit)
00066 
00070   virtual ~MultiLibraryClassLoader();
00071 
00079   template<class Base>
00080   boost::shared_ptr<Base> createInstance(const std::string & class_name)
00081   {
00082     CONSOLE_BRIDGE_logDebug(
00083       "class_loader::MultiLibraryClassLoader: "
00084       "Attempting to create instance of class type %s.",
00085       class_name.c_str());
00086     ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
00087     if (NULL == loader) {
00088       throw class_loader::CreateClassException(
00089               "MultiLibraryClassLoader: Could not create object of class type " +
00090               class_name +
00091               " as no factory exists for it. Make sure that the library exists and "
00092               "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
00093     }
00094 
00095     return loader->createInstance<Base>(class_name);
00096   }
00097 
00106   template<class Base>
00107   boost::shared_ptr<Base>
00108   createInstance(const std::string & class_name, const std::string & library_path)
00109   {
00110     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00111     if (NULL == loader) {
00112       throw class_loader::NoClassLoaderExistsException(
00113               "Could not create instance as there is no ClassLoader in "
00114               "MultiLibraryClassLoader bound to library " + library_path +
00115               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00116     }
00117     return loader->createInstance<Base>(class_name);
00118   }
00119 
00120 #if __cplusplus >= 201103L
00121 
00128   template<class Base>
00129   ClassLoader::UniquePtr<Base> createUniqueInstance(const std::string & class_name)
00130   {
00131     CONSOLE_BRIDGE_logDebug(
00132       "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.",
00133       class_name.c_str());
00134     ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
00135     if (nullptr == loader) {
00136       throw class_loader::CreateClassException(
00137               "MultiLibraryClassLoader: Could not create object of class type " + class_name +
00138               " as no factory exists for it. "
00139               "Make sure that the library exists and was explicitly loaded through "
00140               "MultiLibraryClassLoader::loadLibrary()");
00141     }
00142     return loader->createUniqueInstance<Base>(class_name);
00143   }
00144 
00153   template<class Base>
00154   ClassLoader::UniquePtr<Base>
00155   createUniqueInstance(const std::string & class_name, const std::string & library_path)
00156   {
00157     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00158     if (nullptr == loader) {
00159       throw class_loader::NoClassLoaderExistsException(
00160               "Could not create instance as there is no ClassLoader in "
00161               "MultiLibraryClassLoader bound to library " + library_path +
00162               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00163     }
00164     return loader->createUniqueInstance<Base>(class_name);
00165   }
00166 #endif
00167 
00176   template<class Base>
00177   Base * createUnmanagedInstance(const std::string & class_name)
00178   {
00179     ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
00180     if (NULL == loader) {
00181       throw class_loader::CreateClassException(
00182               "MultiLibraryClassLoader: Could not create class of type " + class_name);
00183     }
00184     return loader->createUnmanagedInstance<Base>(class_name);
00185   }
00186 
00195   template<class Base>
00196   Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path)
00197   {
00198     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00199     if (NULL == loader) {
00200       throw class_loader::NoClassLoaderExistsException(
00201               "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader "
00202               "bound to library " + library_path +
00203               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00204     }
00205     return loader->createUnmanagedInstance<Base>(class_name);
00206   }
00207 
00214   template<class Base>
00215   bool isClassAvailable(const std::string & class_name)
00216   {
00217     std::vector<std::string> available_classes = getAvailableClasses<Base>();
00218     return available_classes.end() != std::find(
00219       available_classes.begin(), available_classes.end(), class_name);
00220   }
00221 
00227   bool isLibraryAvailable(const std::string & library_path);
00228 
00234   template<class Base>
00235   std::vector<std::string> getAvailableClasses()
00236   {
00237     std::vector<std::string> available_classes;
00238     ClassLoaderVector loaders = getAllAvailableClassLoaders();
00239     for (unsigned int c = 0; c < loaders.size(); c++) {
00240       ClassLoader * current = loaders.at(c);
00241       std::vector<std::string> loader_classes = current->getAvailableClasses<Base>();
00242       available_classes.insert(
00243         available_classes.end(), loader_classes.begin(), loader_classes.end());
00244     }
00245     return available_classes;
00246   }
00247 
00253   template<class Base>
00254   std::vector<std::string> getAvailableClassesForLibrary(const std::string & library_path)
00255   {
00256     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00257     std::vector<std::string> available_classes;
00258     if (loader) {
00259       available_classes = loader->getAvailableClasses<Base>();
00260       return available_classes;
00261     } else {
00262       throw class_loader::NoClassLoaderExistsException(
00263               "There is no ClassLoader in MultiLibraryClassLoader bound to library " +
00264               library_path +
00265               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00266     }
00267   }
00268 
00273   std::vector<std::string> getRegisteredLibraries();
00274 
00279   void loadLibrary(const std::string & library_path);
00280 
00285   int unloadLibrary(const std::string & library_path);
00286 
00287 private:
00291   bool isOnDemandLoadUnloadEnabled() {return enable_ondemand_loadunload_;}
00292 
00298   ClassLoader * getClassLoaderForLibrary(const std::string & library_path);
00299 
00305   template<typename Base>
00306   ClassLoader * getClassLoaderForClass(const std::string & class_name)
00307   {
00308     ClassLoaderVector loaders = getAllAvailableClassLoaders();
00309     for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) {
00310       if (!(*i)->isLibraryLoaded()) {
00311         (*i)->loadLibrary();
00312       }
00313       if ((*i)->isClassAvailable<Base>(class_name)) {
00314         return *i;
00315       }
00316     }
00317     return NULL;
00318   }
00319 
00323   ClassLoaderVector getAllAvailableClassLoaders();
00324 
00328   void shutdownAllClassLoaders();
00329 
00330 private:
00331   bool enable_ondemand_loadunload_;
00332   LibraryToClassLoaderMap active_class_loaders_;
00333   boost::mutex loader_mutex_;
00334 };
00335 
00336 
00337 }  // namespace class_loader
00338 #endif  // CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_


class_loader
Author(s): Mirza Shah
autogenerated on Mon Oct 22 2018 05:20:55