Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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);
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 }
00338 #endif // CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_HPP_