multi_library_class_loader.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #ifndef CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_
00031 #define CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_
00032 
00033 #include <boost/thread.hpp>
00034 #include <map>
00035 #include <string>
00036 #include <vector>
00037 
00038 #include "class_loader/class_loader.h"
00039 
00040 // TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release
00041 
00042 namespace class_loader
00043 {
00044 
00045 typedef std::string LibraryPath;
00046 typedef std::map<LibraryPath, class_loader::ClassLoader *> LibraryToClassLoaderMap;
00047 typedef std::vector<ClassLoader *> ClassLoaderVector;
00048 
00053 class MultiLibraryClassLoader
00054 {
00055 public:
00060   MultiLibraryClassLoader(bool enable_ondemand_loadunload);  // NOLINT(runtime/explicit)
00061 
00065   virtual ~MultiLibraryClassLoader();
00066 
00074   template<class Base>
00075   boost::shared_ptr<Base> createInstance(const std::string & class_name)
00076   {
00077     CONSOLE_BRIDGE_logDebug(
00078       "class_loader::MultiLibraryClassLoader: "
00079       "Attempting to create instance of class type %s.",
00080       class_name.c_str());
00081     ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
00082     if (NULL == loader) {
00083       throw class_loader::CreateClassException(
00084               "MultiLibraryClassLoader: Could not create object of class type " +
00085               class_name +
00086               " as no factory exists for it. Make sure that the library exists and "
00087               "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
00088     }
00089 
00090     return loader->createInstance<Base>(class_name);
00091   }
00092 
00101   template<class Base>
00102   boost::shared_ptr<Base>
00103   createInstance(const std::string & class_name, const std::string & library_path)
00104   {
00105     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00106     if (NULL == loader) {
00107       throw class_loader::NoClassLoaderExistsException(
00108               "Could not create instance as there is no ClassLoader in "
00109               "MultiLibraryClassLoader bound to library " + library_path +
00110               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00111     }
00112     return loader->createInstance<Base>(class_name);
00113   }
00114 
00115 #if __cplusplus >= 201103L
00116 
00123   template<class Base>
00124   ClassLoader::UniquePtr<Base> createUniqueInstance(const std::string & class_name)
00125   {
00126     CONSOLE_BRIDGE_logDebug(
00127       "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.",
00128       class_name.c_str());
00129     ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
00130     if (nullptr == loader) {
00131       throw class_loader::CreateClassException(
00132               "MultiLibraryClassLoader: Could not create object of class type " + class_name +
00133               " as no factory exists for it. "
00134               "Make sure that the library exists and was explicitly loaded through "
00135               "MultiLibraryClassLoader::loadLibrary()");
00136     }
00137     return loader->createUniqueInstance<Base>(class_name);
00138   }
00139 
00148   template<class Base>
00149   ClassLoader::UniquePtr<Base>
00150   createUniqueInstance(const std::string & class_name, const std::string & library_path)
00151   {
00152     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00153     if (nullptr == loader) {
00154       throw class_loader::NoClassLoaderExistsException(
00155               "Could not create instance as there is no ClassLoader in "
00156               "MultiLibraryClassLoader bound to library " + library_path +
00157               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00158     }
00159     return loader->createUniqueInstance<Base>(class_name);
00160   }
00161 #endif
00162 
00171   template<class Base>
00172   Base * createUnmanagedInstance(const std::string & class_name)
00173   {
00174     ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
00175     if (NULL == loader) {
00176       throw class_loader::CreateClassException(
00177               "MultiLibraryClassLoader: Could not create class of type " + class_name);
00178     }
00179     return loader->createUnmanagedInstance<Base>(class_name);
00180   }
00181 
00190   template<class Base>
00191   Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path)
00192   {
00193     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00194     if (NULL == loader) {
00195       throw class_loader::NoClassLoaderExistsException(
00196               "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader "
00197               "bound to library " + library_path +
00198               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00199     }
00200     return loader->createUnmanagedInstance<Base>(class_name);
00201   }
00202 
00209   template<class Base>
00210   bool isClassAvailable(const std::string & class_name)
00211   {
00212     std::vector<std::string> available_classes = getAvailableClasses<Base>();
00213     return available_classes.end() != std::find(
00214       available_classes.begin(), available_classes.end(), class_name);
00215   }
00216 
00222   bool isLibraryAvailable(const std::string & library_path);
00223 
00229   template<class Base>
00230   std::vector<std::string> getAvailableClasses()
00231   {
00232     std::vector<std::string> available_classes;
00233     ClassLoaderVector loaders = getAllAvailableClassLoaders();
00234     for (unsigned int c = 0; c < loaders.size(); c++) {
00235       ClassLoader * current = loaders.at(c);
00236       std::vector<std::string> loader_classes = current->getAvailableClasses<Base>();
00237       available_classes.insert(
00238         available_classes.end(), loader_classes.begin(), loader_classes.end());
00239     }
00240     return available_classes;
00241   }
00242 
00248   template<class Base>
00249   std::vector<std::string> getAvailableClassesForLibrary(const std::string & library_path)
00250   {
00251     ClassLoader * loader = getClassLoaderForLibrary(library_path);
00252     std::vector<std::string> available_classes;
00253     if (loader) {
00254       available_classes = loader->getAvailableClasses<Base>();
00255       return available_classes;
00256     } else {
00257       throw class_loader::NoClassLoaderExistsException(
00258               "There is no ClassLoader in MultiLibraryClassLoader bound to library " +
00259               library_path +
00260               " Ensure you called MultiLibraryClassLoader::loadLibrary()");
00261     }
00262   }
00263 
00268   std::vector<std::string> getRegisteredLibraries();
00269 
00274   void loadLibrary(const std::string & library_path);
00275 
00280   int unloadLibrary(const std::string & library_path);
00281 
00282 private:
00286   bool isOnDemandLoadUnloadEnabled() {return enable_ondemand_loadunload_;}
00287 
00293   ClassLoader * getClassLoaderForLibrary(const std::string & library_path);
00294 
00300   template<typename Base>
00301   ClassLoader * getClassLoaderForClass(const std::string & class_name)
00302   {
00303     ClassLoaderVector loaders = getAllAvailableClassLoaders();
00304     for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) {
00305       if (!(*i)->isLibraryLoaded()) {
00306         (*i)->loadLibrary();
00307       }
00308       if ((*i)->isClassAvailable<Base>(class_name)) {
00309         return *i;
00310       }
00311     }
00312     return NULL;
00313   }
00314 
00318   ClassLoaderVector getAllAvailableClassLoaders();
00319 
00323   void shutdownAllClassLoaders();
00324 
00325 private:
00326   bool enable_ondemand_loadunload_;
00327   LibraryToClassLoaderMap active_class_loaders_;
00328   boost::mutex loader_mutex_;
00329 };
00330 
00331 
00332 }  // namespace class_loader
00333 #endif  // CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_


class_loader
Author(s): Mirza Shah
autogenerated on Thu Dec 7 2017 04:48:01