PluginManager.h
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2014 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00027 //----------------------------------------------------------------------
00028 #ifndef ICL_CORE_PLUGIN_PLUGIN_MANAGER_H_INCLUDED
00029 #define ICL_CORE_PLUGIN_PLUGIN_MANAGER_H_INCLUDED
00030 
00031 #include "icl_core_plugin/ImportExport.h"
00032 #include "icl_core_plugin/Logging.h"
00033 #include "icl_core_plugin/PluginManagerBase.h"
00034 
00035 #include <boost/filesystem.hpp>
00036 
00037 #include <cassert>
00038 #include <string>
00039 #include <list>
00040 #include <map>
00041 #include <iostream>
00042 #include <sstream>
00043 
00044 #include <ltdl.h>
00045 
00046 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00047 # include "icl_core/Deprecate.h"
00048 #endif
00049 
00050 namespace icl_core {
00052 namespace plugin {
00053 
00056 template <class T, const char* const plugin_dir>
00057 class PluginManager: public PluginManagerBase
00058 {
00059 public:
00060   ~PluginManager()
00061   {
00062     while (!m_plugin_handles.empty() && !m_loaded_plugins.empty())
00063     {
00064       closePluginHandle(m_loaded_plugins.begin()->first);
00065     }
00066 
00067     lt_dlexit();
00068     static PluginManager<T, plugin_dir>* m_instance;
00069     m_instance = 0;
00070     (void) m_instance;
00071   }
00072 
00074   static PluginManager<T, plugin_dir> *instance()
00075   {
00077     static PluginManager<T, plugin_dir> *m_instance = 0;
00078 
00079     if (!m_instance)
00080     {
00081       m_instance = new PluginManager<T, plugin_dir>();
00082     }
00083 
00084     assert(m_instance);
00085     return m_instance;
00086   }
00087 
00089   bool initialize(bool load_lazy = true, bool recursive_search = false)
00090   {
00091     if (isInitialized() && loadLazy() && !load_lazy)
00092     {
00093       loadPlugins();
00094       return true;
00095     }
00096 
00097     if (isInitialized())
00098     {
00099       LOGGING_WARNING(Plugin, "The plugin framework is already initialized!" << icl_core::logging::endl);
00100       return true;
00101     }
00102 
00103     initializePlugins(recursive_search);
00104 
00105     if (!load_lazy)
00106     {
00107       loadPlugins();
00108     }
00109     else
00110     {
00111       m_lazy_loading = true;
00112     }
00113 
00114     return true;
00115   }
00116 
00117   bool isInitialized() const
00118   {
00119     return m_initialized;
00120   }
00121 
00122   bool loadLazy() const
00123   {
00124     return m_lazy_loading;
00125   }
00126 
00129   std::list<std::string> availablePlugins()
00130   {
00131     if (!isInitialized())
00132     {
00133       initialize(false);
00134     }
00135 
00136     if (loadLazy())
00137     {
00138       loadPlugins();
00139     }
00140 
00141     std::list<std::string> result;
00142     typename std::map<std::string, lt_dlhandle>::const_iterator iter;
00143     for (iter = m_plugin_handles.begin(); iter != m_plugin_handles.end(); ++iter)
00144     {
00145       result.push_back(iter->first);
00146     }
00147 
00148     typename std::map<std::string, T*>::const_iterator siter;
00149     for (siter = m_static_plugins.begin(); siter != m_static_plugins.end(); ++siter)
00150     {
00151       result.push_back(siter->first);
00152     }
00153 
00154     return result;
00155   }
00156 
00159   std::list<T*> plugins()
00160   {
00161     if (!isInitialized())
00162     {
00163       initialize(false);
00164     }
00165 
00166     if (loadLazy())
00167     {
00168       loadPlugins();
00169     }
00170 
00171     std::list<T*> result;
00172     typename std::map<std::string, T*>::const_iterator iter;
00173     for (iter = m_loaded_plugins.begin(); iter != m_loaded_plugins.end(); ++iter)
00174     {
00175       result.push_back(iter->second);
00176     }
00177 
00178     typename std::map<std::string, T*>::const_iterator siter;
00179     for (siter = m_static_plugins.begin(); siter != m_static_plugins.end(); ++siter)
00180     {
00181       result.push_back(siter->second);
00182     }
00183 
00184     return result;
00185   }
00186 
00190   T* plugin(const std::string &identifier)
00191   {
00192     if (!isInitialized())
00193     {
00194       initialize(false);
00195     }
00196 
00197     if (loadLazy())
00198     {
00199       loadPlugins();
00200     }
00201 
00202     if (m_static_plugins.find(identifier) != m_static_plugins.end())
00203     {
00204       return m_static_plugins[identifier];
00205     }
00206 
00207     return m_loaded_plugins[identifier];
00208   }
00209 
00213   T* createPluginInstance(const std::string &identifier)
00214   {
00215     if (!isInitialized())
00216     {
00217       initialize(false);
00218     }
00219 
00220     if (loadLazy())
00221     {
00222       loadPlugins();
00223     }
00224 
00225     lt_dlhandle plugin_handle = m_plugin_handles[identifier];
00226     return loadPluginInstance(plugin_handle, identifier);
00227   }
00228 
00237   void addStaticPlugin(T* instance)
00238   {
00239     removeStaticPlugin(instance->Identifier());
00240     m_static_plugins[instance->Identifier()] = instance;
00241     LOGGING_DEBUG(Plugin, "Static plugin " << instance->Identifier() << " added." << icl_core::logging::endl);
00242   }
00243 
00247   void removeStaticPlugin(const std::string &identifier)
00248   {
00249     m_static_plugins.erase(identifier);
00250     LOGGING_DEBUG(Plugin, "Static plugin " << identifier << " removed."
00251                   << icl_core::logging::endl);
00252   }
00253 
00258   bool isStaticPlugin(const std::string &identifier) const
00259   {
00260     return m_static_plugins.find(identifier) != m_static_plugins.end();
00261   }
00262 
00264 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00265 
00269   static ICL_CORE_VC_DEPRECATE_STYLE PluginManager<T, plugin_dir> *Instance()
00270     ICL_CORE_GCC_DEPRECATE_STYLE
00271   { return instance(); }
00272 
00276   ICL_CORE_VC_DEPRECATE_STYLE bool Initialize(bool load_lazy = true,
00277                                               bool recursive_search = false)
00278     ICL_CORE_GCC_DEPRECATE_STYLE
00279   { return initialize(load_lazy, recursive_search); }
00280 
00281   ICL_CORE_VC_DEPRECATE_STYLE bool IsInitialized() const
00282     ICL_CORE_GCC_DEPRECATE_STYLE
00283   { return isInitialized(); }
00284 
00285   ICL_CORE_VC_DEPRECATE_STYLE bool LoadLazy() const
00286     ICL_CORE_GCC_DEPRECATE_STYLE
00287   { return loadLazy(); }
00288 
00292   ICL_CORE_VC_DEPRECATE_STYLE std::list<std::string> AvailablePlugins()
00293     ICL_CORE_GCC_DEPRECATE_STYLE
00294   { return availablePlugins(); }
00295 
00299   ICL_CORE_VC_DEPRECATE_STYLE std::list<T*> Plugins()
00300     ICL_CORE_GCC_DEPRECATE_STYLE
00301   { return plugins(); }
00302 
00306   ICL_CORE_VC_DEPRECATE_STYLE T* Plugin(const std::string &identifier)
00307     ICL_CORE_GCC_DEPRECATE_STYLE
00308   { return plugin(identifier); }
00309 
00313   ICL_CORE_VC_DEPRECATE_STYLE T* CreatePluginInstance(const std::string &identifier)
00314     ICL_CORE_GCC_DEPRECATE_STYLE
00315   { return createPluginInstance(identifier); }
00316 
00320   ICL_CORE_VC_DEPRECATE_STYLE void AddStaticPlugin(T* instance)
00321     ICL_CORE_GCC_DEPRECATE_STYLE
00322   { addStaticPlugin(instance); }
00323 
00327   ICL_CORE_VC_DEPRECATE_STYLE void RemoveStaticPlugin(const std::string &identifier)
00328     ICL_CORE_GCC_DEPRECATE_STYLE
00329   { removeStaticPlugin(identifier); }
00330 
00335   ICL_CORE_VC_DEPRECATE_STYLE bool IsStaticPlugin(const std::string &identifier) const
00336     ICL_CORE_GCC_DEPRECATE_STYLE
00337   { return isStaticPlugin(identifier); }
00338 
00339 #endif
00340 
00341 
00342 protected:
00344   PluginManager()
00345     : PluginManagerBase(plugin_dir),
00346       m_initialized(false),
00347       m_lazy_loading(false)
00348   {
00349     lt_dlinit();
00350   }
00351 
00355   void initializePlugins(bool recursive_search)
00356   {
00357     assert(!isInitialized());
00358     clearErrorMessages();
00359     m_initialized = true;
00360 
00361     StringList paths = pluginPaths();
00362     for (StringList::const_iterator iter = paths.begin(); iter != paths.end(); ++iter)
00363     {
00364       std::string path = *iter;
00365       boost::filesystem::path bpath(path);
00366       LOGGING_TRACE(Plugin, "Loading plugins from " << path << icl_core::logging::endl);
00367 
00368       bool found = false;
00369       try
00370       {
00371         found = exists(bpath);
00372       }
00373       catch (const boost::filesystem::filesystem_error &e)
00374       {
00375         LOGGING_DEBUG(Plugin, "Exception when examining directory " << path
00376                       << ": " << e.what() << icl_core::logging::endl);
00377         // Ignored
00378       }
00379 
00380       if (!found)
00381       {
00382         LOGGING_DEBUG(Plugin, "Ignoring non-existing plugin path " << path << icl_core::logging::endl);
00383         continue;
00384       }
00385 
00386       if (!recursive_search)
00387       {
00388         boost::filesystem::directory_iterator end_iter;
00389         for (boost::filesystem::directory_iterator dir_iter(bpath); dir_iter != end_iter; ++dir_iter)
00390         {
00391           if (boost::filesystem::is_regular_file(dir_iter->status()))
00392           {
00393 #if BOOST_FILESYSTEM_VERSION == 2
00394             loadHandle(dir_iter->string());
00395 #else
00396             loadHandle(dir_iter->path().string());
00397 #endif
00398           }
00399         }
00400       }
00401       else
00402       {
00403         boost::filesystem::recursive_directory_iterator end_iter;
00404         for (boost::filesystem::recursive_directory_iterator dir_iter(bpath);
00405              dir_iter != end_iter; ++dir_iter)
00406         {
00407           if (boost::filesystem::is_regular_file(dir_iter->status()))
00408           {
00409 #if BOOST_FILESYSTEM_VERSION == 2
00410             loadHandle(dir_iter->string());
00411 #else
00412             loadHandle(dir_iter->path().string());
00413 #endif
00414           }
00415         }
00416       }
00417     }
00418 
00419     LOGGING_DEBUG(Plugin, "Initialized " << m_plugin_handles.size() << " plugins."
00420                   << icl_core::logging::endl);
00421   }
00422 
00425   void loadHandle(std::string plugin)
00426   {
00427     lt_dlhandle plugin_handle = lt_dlopen(plugin.c_str());
00428 
00429     // Clear errors.
00430     lt_dlerror();
00431     typename T::identifier* get_identifier
00432       = (typename T::identifier*) lt_dlsym(plugin_handle, "identifier");
00433 
00434     typename T::basetype* get_basetype
00435       = (typename T::basetype*) lt_dlsym(plugin_handle, "basetype");
00436 
00437     const char* dlsym_error = lt_dlerror();
00438     if (dlsym_error)
00439     {
00440 #ifdef _WIN32
00441       LPVOID msg_buffer;
00442       unsigned error_code = GetLastError();
00443 
00444       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
00445                     | FORMAT_MESSAGE_FROM_SYSTEM,
00446                     NULL,
00447                     error_code,
00448                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00449                     (LPTSTR) &msg_buffer,
00450                     0, NULL);
00451 
00452       std::ostringstream error;
00453       error << "Could not open dll: (" << error_code << ") " << msg_buffer;
00454       addErrorMessage(error.str());
00456       //LOGGING_ERROR(Plugin, error.str() << icl_core::logging::endl);
00457       printf("could not open dll: (%d) %s\n", error_code, msg_buffer);
00458       LocalFree(msg_buffer);
00459 #else // _WIN32
00460       std::ostringstream error;
00461       error << "Cannot load plugin " << plugin << ": " << dlsym_error;
00462       addErrorMessage(error.str());
00463       LOGGING_ERROR(Plugin, error.str() << icl_core::logging::endl);
00464       // cannot find symbol
00465 #endif // _WIN32
00466     }
00467     else
00468     {
00469       if (!get_identifier || !get_basetype)
00470       {
00471         std::ostringstream error;
00472         error << "Identifier or basetype method missing in plugin " << plugin;
00473         addErrorMessage(error.str());
00474         LOGGING_ERROR(Plugin, error.str() << icl_core::logging::endl);
00475       }
00476       else if (strcmp(get_basetype(), typeid(T).name()) != 0)
00477       {
00478         LOGGING_WARNING(Plugin, "Plugin type mismatch: Exptected " << typeid(T).name()
00479                         << ", got " << get_basetype() << icl_core::logging::endl);
00480       }
00481       else
00482       {
00483         m_plugin_handles[get_identifier()] = plugin_handle;
00484         LOGGING_DEBUG(Plugin, "Initialized plugin " << get_identifier() << " of basetype "
00485                       << get_basetype() << icl_core::logging::endl);
00486       }
00487     }
00488   }
00489 
00493   void loadPlugins()
00494   {
00495     m_lazy_loading = false;
00496 
00497     typename std::map<std::string, lt_dlhandle>::const_iterator iter;
00498     for (iter = m_plugin_handles.begin(); iter != m_plugin_handles.end(); ++iter)
00499     {
00500       if (m_loaded_plugins.find(iter->first) == m_loaded_plugins.end())
00501       {
00502         m_loaded_plugins[iter->first] = createPluginInstance(iter->first);
00503       }
00504     }
00505 
00506     LOGGING_DEBUG(Plugin, "Loaded " << m_loaded_plugins.size() << " plugins." << icl_core::logging::endl);
00507   }
00508 
00511   void unloadPlugin(const std::string &identifier)
00512   {
00513     delete m_loaded_plugins[identifier];
00514     m_loaded_plugins.erase(identifier);
00515   }
00516 
00519   void closePluginHandle(const std::string &identifier)
00520   {
00521     lt_dlhandle plugin_handle = m_plugin_handles[identifier];
00522     if (plugin_handle)
00523     {
00524       LOGGING_DEBUG(Plugin, "Close plugin " << identifier << icl_core::logging::endl);
00525 
00526       if (m_loaded_plugins.find(identifier) != m_loaded_plugins.end())
00527       {
00528         T* plugin_instance = m_loaded_plugins[identifier];
00529         delete plugin_instance;
00530         m_loaded_plugins.erase(identifier);
00531       }
00532 
00533       lt_dlclose(plugin_handle);
00534     }
00535     m_plugin_handles.erase(identifier);
00536   }
00537 
00540   T* loadPluginInstance(lt_dlhandle plugin_handle, const std::string &identifier)
00541   {
00542     if (plugin_handle)
00543     {
00544       // clear errors
00545       lt_dlerror();
00546 
00547       typename T::load_plugin* create_instance
00548         = (typename T::load_plugin*) lt_dlsym(plugin_handle,
00549                                               "load_plugin");
00550       const char* dlsym_error = lt_dlerror();
00551       if (dlsym_error)
00552       {
00553 #ifdef _WIN32
00554         LPVOID msg_buffer;
00555         unsigned error_code = GetLastError();
00556 
00557         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
00558                       | FORMAT_MESSAGE_FROM_SYSTEM,
00559                       NULL,
00560                       error_code,
00561                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00562                       (LPTSTR) &msg_buffer,
00563                       0, NULL);
00564 
00565         std::ostringstream error;
00566         error << "Could not open dll: (" << error_code << ") " << msg_buffer;
00567         addErrorMessage(error.str());
00568         LOGGING_ERROR(Plugin, error.str() << icl_core::logging::endl);
00569         LocalFree(msg_buffer);
00570 #else // _WIN32
00571         std::ostringstream error;
00572         error << "Cannot load plugin " << identifier << ": " << dlsym_error;
00573         addErrorMessage(error.str());
00574         LOGGING_ERROR(Plugin, error.str() << icl_core::logging::endl);
00575         // cannot find symbol
00576 #endif // _WIN32
00577       }
00578       else
00579       {
00580         T* plugin_instance = create_instance();
00581         if (!plugin_instance)
00582         {
00583           std::ostringstream error;
00584           error << "Cannot cast plugin " << identifier;
00585           addErrorMessage(error.str());
00586           LOGGING_ERROR(Plugin, error.str() << icl_core::logging::endl);
00587         }
00588         else
00589         {
00590           LOGGING_DEBUG(Plugin, "Loaded plugin " << plugin_instance->Identifier() << icl_core::logging::endl);
00591         }
00592         return plugin_instance;
00593       }
00594     }
00595     LOGGING_ERROR(Plugin, "No valid plugin handle available for " << identifier << icl_core::logging::endl);
00596     return NULL;
00597   }
00598 
00600 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00601 
00606   ICL_CORE_VC_DEPRECATE_STYLE void InitializePlugins(bool recursive_search)
00607     ICL_CORE_GCC_DEPRECATE_STYLE
00608   { initializePlugins(recursive_search); }
00609 
00613   ICL_CORE_VC_DEPRECATE_STYLE void LoadHandle(std::string plugin)
00614     ICL_CORE_GCC_DEPRECATE_STYLE
00615   { loadHandle(plugin); }
00616 
00620   ICL_CORE_VC_DEPRECATE_STYLE void LoadPlugins()
00621     ICL_CORE_GCC_DEPRECATE_STYLE
00622   { loadPlugins(); }
00623 
00627   ICL_CORE_VC_DEPRECATE_STYLE void UnloadPlugin(const std::string &identifier)
00628     ICL_CORE_GCC_DEPRECATE_STYLE
00629   { unloadPlugin(identifier); }
00630 
00634   ICL_CORE_VC_DEPRECATE_STYLE void ClosePluginHandle(const std::string &identifier)
00635     ICL_CORE_GCC_DEPRECATE_STYLE
00636   { closePluginHandle(identifier); }
00637 
00641   ICL_CORE_VC_DEPRECATE_STYLE T* LoadPluginInstance(lt_dlhandle plugin_handle, const std::string &identifier)
00642     ICL_CORE_GCC_DEPRECATE_STYLE
00643   { return loadPluginInstance(plugin_handle, identifier); }
00644 
00645 #endif
00646 
00647 
00649   std::map<std::string, T*> m_loaded_plugins;
00650 
00652   std::map<std::string, lt_dlhandle> m_plugin_handles;
00653 
00655   std::map<std::string, T*> m_static_plugins;
00656 
00657   bool m_initialized;
00658 
00659   bool m_lazy_loading;
00660 };
00661 
00662 }
00663 }
00664 
00665 #endif


schunk_svh_driver
Author(s): Georg Heppner
autogenerated on Fri Aug 28 2015 12:59:19