common/include/pion/PionPlugin.hpp

00001 // -----------------------------------------------------------------------
00002 // pion-common: a collection of common libraries used by the Pion Platform
00003 // -----------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Distributed under the Boost Software License, Version 1.0.
00007 // See http://www.boost.org/LICENSE_1_0.txt
00008 //
00009 
00010 #ifndef __PION_PIONPLUGIN_HEADER__
00011 #define __PION_PIONPLUGIN_HEADER__
00012 
00013 #include <vector>
00014 #include <string>
00015 #include <map>
00016 #include <list>
00017 #include <boost/thread/mutex.hpp>
00018 #include <boost/filesystem/path.hpp>
00019 #include <pion/PionConfig.hpp>
00020 #include <pion/PionException.hpp>
00021 
00022 
00023 namespace pion {    // begin namespace pion
00024 
00028 class PION_COMMON_API PionPlugin {
00029 public:
00030 
00032     class PluginUndefinedException : public std::exception {
00033     public:
00034         virtual const char* what() const throw() {
00035             return "Plug-in was not loaded properly";
00036         }
00037     };
00038     
00040     class DirectoryNotFoundException : public PionException {
00041     public:
00042         DirectoryNotFoundException(const std::string& dir)
00043             : PionException("Plug-in directory not found: ", dir) {}
00044     };
00045 
00047     class PluginNotFoundException : public PionException {
00048     public:
00049         PluginNotFoundException(const std::string& file)
00050             : PionException("Plug-in library not found: ", file) {}
00051     };
00052     
00054     class OpenPluginException : public PionException {
00055     public:
00056         OpenPluginException(const std::string& file)
00057             : PionException("Unable to open plug-in library: ", file) {}
00058     };
00059     
00061     class PluginMissingCreateException : public PionException {
00062     public:
00063         PluginMissingCreateException(const std::string& file)
00064             : PionException("Plug-in library does not include create() symbol: ", file) {}
00065     };
00066     
00068     class PluginMissingDestroyException : public PionException {
00069     public:
00070         PluginMissingDestroyException(const std::string& file)
00071             : PionException("Plug-in library does not include destroy() symbol: ", file) {}
00072     };
00073 
00081     static inline bool findPluginFile(std::string& path_to_file,
00082                                       const std::string& name)
00083     {
00084         return findFile(path_to_file, name, PION_PLUGIN_EXTENSION);
00085     }
00086 
00094     static inline bool findConfigFile(std::string& path_to_file,
00095                                       const std::string& name)
00096     {
00097         return findFile(path_to_file, name, PION_CONFIG_EXTENSION);
00098     }
00099     
00107     static bool findStaticEntryPoint(const std::string& plugin_name,
00108                                      void **create_func,
00109                                      void **destroy_func);
00110     
00118     static void addStaticEntryPoint(const std::string& plugin_name,
00119                                     void *create_func,
00120                                     void *destroy_func);
00121     
00130     static void checkCygwinPath(boost::filesystem::path& final_path,
00131                                 const std::string& path_string);
00132 
00134     static void addPluginDirectory(const std::string& dir);
00135     
00137     static void resetPluginDirectories(void);
00138     
00139 
00140     // default destructor
00141     virtual ~PionPlugin() { releaseData(); }
00142     
00144     inline bool is_open(void) const { return (m_plugin_data != NULL); }
00145     
00147     inline std::string getPluginName(void) const {
00148         return (is_open() ? m_plugin_data->m_plugin_name : std::string());
00149     }
00150 
00152     static void getAllPluginNames(std::vector<std::string>& plugin_names);
00153 
00166     void open(const std::string& plugin_name);
00167 
00180     void openFile(const std::string& plugin_file);
00181 
00190     void openStaticLinked(const std::string& plugin_name,
00191                           void *create_func,
00192                           void *destroy_func);
00193 
00195     inline void close(void) { releaseData(); }
00196 
00197 protected:
00198     
00202     struct PionPluginData
00203     {
00205         PionPluginData(void)
00206             : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
00207             m_references(0)
00208         {}
00209         PionPluginData(const std::string& plugin_name)
00210             : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
00211             m_plugin_name(plugin_name), m_references(0)
00212         {}
00213         PionPluginData(const PionPluginData& p)
00214             : m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func),
00215             m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name),
00216             m_references(p.m_references)
00217         {}
00218         
00220         void *          m_lib_handle;
00221         
00223         void *          m_create_func;
00224         
00226         void *          m_destroy_func;
00227         
00229         std::string     m_plugin_name;
00230         
00232         unsigned long   m_references;
00233     };
00234 
00235     
00237     PionPlugin(void) : m_plugin_data(NULL) {}
00238     
00240     PionPlugin(const PionPlugin& p) : m_plugin_data(NULL) { grabData(p); }
00241 
00243     PionPlugin& operator=(const PionPlugin& p) { grabData(p); return *this; }
00244 
00246     inline void *getCreateFunction(void) {
00247         return (is_open() ? m_plugin_data->m_create_func : NULL);
00248     }
00249 
00251     inline void *getDestroyFunction(void) {
00252         return (is_open() ? m_plugin_data->m_destroy_func : NULL);
00253     }
00254 
00256     void releaseData(void);
00257     
00259     void grabData(const PionPlugin& p);
00260 
00261     
00262 private:
00263 
00265     class StaticEntryPoint
00266     {
00267     public:
00268         StaticEntryPoint(const std::string& name, void *create, void *destroy)
00269             : m_plugin_name(name), m_create_func(create), m_destroy_func(destroy)
00270             {}
00271         std::string  m_plugin_name;
00272         void *       m_create_func;
00273         void *       m_destroy_func;
00274     };
00275 
00277     typedef std::list<StaticEntryPoint>     StaticEntryPointList;
00278     
00280     typedef std::map<std::string, PionPluginData*>  PluginMap;
00281 
00282     
00292     static bool findFile(std::string& path_to_file, const std::string& name,                             
00293                          const std::string& extension);
00294     
00305     static bool checkForFile(std::string& final_path, const std::string& start_path,
00306                              const std::string& name, const std::string& extension);
00307     
00314     static void openPlugin(const std::string& plugin_file,
00315                            PionPluginData& plugin_data);
00316 
00318     static std::string getPluginName(const std::string& plugin_file);
00319     
00321     static void *loadDynamicLibrary(const std::string& plugin_file);
00322     
00324     static void closeDynamicLibrary(void *lib_handle);
00325     
00327     static void *getLibrarySymbol(void *lib_handle, const std::string& symbol);
00328     
00329     
00331     static const std::string            PION_PLUGIN_CREATE;
00332     
00334     static const std::string            PION_PLUGIN_DESTROY;
00335     
00337     static const std::string            PION_PLUGIN_EXTENSION;
00338     
00340     static const std::string            PION_CONFIG_EXTENSION;
00341     
00343     static std::vector<std::string>     m_plugin_dirs;
00344     
00346     static PluginMap                    m_plugin_map;
00347     
00349     static boost::mutex                 m_plugin_mutex;
00350 
00352     static StaticEntryPointList         *m_entry_points_ptr;
00353 
00355     PionPluginData *                    m_plugin_data;
00356 };
00357 
00358 
00363 template <typename InterfaceClassType>
00364 class PionPluginPtr :
00365     public PionPlugin
00366 {
00367 protected:
00368     
00370     typedef InterfaceClassType* CreateObjectFunction(void);
00371     
00373     typedef void DestroyObjectFunction(InterfaceClassType*);
00374 
00375     
00376 public:
00377 
00379     PionPluginPtr(void) : PionPlugin() {}
00380     virtual ~PionPluginPtr() {}
00381     
00383     PionPluginPtr(const PionPluginPtr& p) : PionPlugin(p) {}
00384 
00386     PionPluginPtr& operator=(const PionPluginPtr& p) { grabData(p); return *this; }
00387 
00389     inline InterfaceClassType *create(void) {
00390         CreateObjectFunction *create_func =
00391             (CreateObjectFunction*)(getCreateFunction());
00392         if (create_func == NULL)
00393             throw PluginUndefinedException();
00394         return create_func();
00395     }
00396     
00398     inline void destroy(InterfaceClassType *object_ptr) {
00399         DestroyObjectFunction *destroy_func =
00400             (DestroyObjectFunction*)(getDestroyFunction());
00401         if (destroy_func == NULL)
00402             throw PluginUndefinedException();
00403         destroy_func(object_ptr);
00404     }
00405 };
00406 
00407 
00421 #ifdef PION_STATIC_LINKING
00422 
00423 #define PION_DECLARE_PLUGIN(plugin_name)    \
00424     class plugin_name;                      \
00425     extern "C" plugin_name *pion_create_##plugin_name(void); \
00426     extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \
00427     static pion::StaticEntryPointHelper helper_##plugin_name(#plugin_name, pion_create_##plugin_name, pion_destroy_##plugin_name);
00428 
00430 class StaticEntryPointHelper {
00431 public:
00432     StaticEntryPointHelper(const std::string& name, void *create, void *destroy)
00433     {
00434         pion::PionPlugin::addStaticEntryPoint(name, create, destroy);
00435     }
00436 };
00437 
00438 #else
00439 
00440 #define PION_DECLARE_PLUGIN(plugin_name)
00441 
00442 #endif
00443 
00444 }   // end namespace pion
00445 
00446 #endif

Generated on Fri Apr 30 14:48:53 2010 for pion-net by  doxygen 1.4.7