pion
5.0.6
|
00001 // --------------------------------------------------------------------- 00002 // pion: a Boost C++ framework for building lightweight HTTP interfaces 00003 // --------------------------------------------------------------------- 00004 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion) 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_PLUGIN_HEADER__ 00011 #define __PION_PLUGIN_HEADER__ 00012 00013 #include <vector> 00014 #include <string> 00015 #include <map> 00016 #include <list> 00017 #include <boost/noncopyable.hpp> 00018 #include <boost/thread/once.hpp> 00019 #include <boost/thread/mutex.hpp> 00020 #include <boost/filesystem/path.hpp> 00021 #include <pion/config.hpp> 00022 #include <pion/error.hpp> 00023 00024 00025 namespace pion { // begin namespace pion 00026 00030 class PION_API plugin { 00031 public: 00032 00040 static inline bool find_plugin_file(std::string& path_to_file, 00041 const std::string& name) 00042 { 00043 return find_file(path_to_file, name, PION_PLUGIN_EXTENSION); 00044 } 00045 00053 static inline bool find_config_file(std::string& path_to_file, 00054 const std::string& name) 00055 { 00056 return find_file(path_to_file, name, PION_CONFIG_EXTENSION); 00057 } 00058 00067 static void add_static_entry_point(const std::string& plugin_name, 00068 void *create_func, 00069 void *destroy_func); 00070 00079 static void check_cygwin_path(boost::filesystem::path& final_path, 00080 const std::string& path_string); 00081 00083 static void add_plugin_directory(const std::string& dir); 00084 00086 static void reset_plugin_directories(void); 00087 00088 00089 // default destructor 00090 virtual ~plugin() { release_data(); } 00091 00093 inline bool is_open(void) const { return (m_plugin_data != NULL); } 00094 00096 inline std::string get_plugin_name(void) const { 00097 return (is_open() ? m_plugin_data->m_plugin_name : std::string()); 00098 } 00099 00101 static void get_all_plugin_names(std::vector<std::string>& plugin_names); 00102 00115 void open(const std::string& plugin_name); 00116 00129 void open_file(const std::string& plugin_file); 00130 00132 inline void close(void) { release_data(); } 00133 00134 protected: 00135 00139 struct data_type 00140 { 00142 data_type(void) 00143 : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL), 00144 m_references(0) 00145 {} 00146 data_type(const std::string& plugin_name) 00147 : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL), 00148 m_plugin_name(plugin_name), m_references(0) 00149 {} 00150 data_type(const data_type& p) 00151 : m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func), 00152 m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name), 00153 m_references(p.m_references) 00154 {} 00155 00157 void * m_lib_handle; 00158 00160 void * m_create_func; 00161 00163 void * m_destroy_func; 00164 00166 std::string m_plugin_name; 00167 00169 unsigned long m_references; 00170 }; 00171 00172 00174 plugin(void) : m_plugin_data(NULL) {} 00175 00177 plugin(const plugin& p) : m_plugin_data(NULL) { grab_data(p); } 00178 00180 plugin& operator=(const plugin& p) { grab_data(p); return *this; } 00181 00183 inline void *get_create_function(void) { 00184 return (is_open() ? m_plugin_data->m_create_func : NULL); 00185 } 00186 00188 inline void *get_destroy_function(void) { 00189 return (is_open() ? m_plugin_data->m_destroy_func : NULL); 00190 } 00191 00193 void release_data(void); 00194 00196 void grab_data(const plugin& p); 00197 00198 00199 private: 00200 00202 typedef std::map<std::string, data_type*> map_type; 00203 00205 struct config_type { 00207 std::vector<std::string> m_plugin_dirs; 00208 00210 map_type m_plugin_map; 00211 00213 boost::mutex m_plugin_mutex; 00214 }; 00215 00216 00218 static inline config_type& get_plugin_config(void) { 00219 boost::call_once(plugin::create_plugin_config, m_instance_flag); 00220 return *m_config_ptr; 00221 } 00222 00224 static void create_plugin_config(void); 00225 00235 static bool find_file(std::string& path_to_file, const std::string& name, 00236 const std::string& extension); 00237 00248 static bool check_for_file(std::string& final_path, const std::string& start_path, 00249 const std::string& name, const std::string& extension); 00250 00257 static void open_plugin(const std::string& plugin_file, 00258 data_type& plugin_data); 00259 00261 static std::string get_plugin_name(const std::string& plugin_file); 00262 00264 static void *load_dynamic_library(const std::string& plugin_file); 00265 00267 static void close_dynamic_library(void *lib_handle); 00268 00270 static void *get_library_symbol(void *lib_handle, const std::string& symbol); 00271 00272 00274 static const std::string PION_PLUGIN_CREATE; 00275 00277 static const std::string PION_PLUGIN_DESTROY; 00278 00280 static const std::string PION_PLUGIN_EXTENSION; 00281 00283 static const std::string PION_CONFIG_EXTENSION; 00284 00286 static boost::once_flag m_instance_flag; 00287 00289 static config_type * m_config_ptr; 00290 00292 data_type * m_plugin_data; 00293 }; 00294 00295 00300 template <typename InterfaceClassType> 00301 class plugin_ptr : 00302 public plugin 00303 { 00304 protected: 00305 00307 typedef InterfaceClassType* CreateObjectFunction(void); 00308 00310 typedef void DestroyObjectFunction(InterfaceClassType*); 00311 00312 00313 public: 00314 00316 plugin_ptr(void) : plugin() {} 00317 virtual ~plugin_ptr() {} 00318 00320 plugin_ptr(const plugin_ptr& p) : plugin(p) {} 00321 00323 plugin_ptr& operator=(const plugin_ptr& p) { grab_data(p); return *this; } 00324 00326 inline InterfaceClassType *create(void) { 00327 CreateObjectFunction *create_func = 00328 (CreateObjectFunction*)(get_create_function()); 00329 if (create_func == NULL) 00330 BOOST_THROW_EXCEPTION( error::plugin_undefined() ); 00331 return create_func(); 00332 } 00333 00335 inline void destroy(InterfaceClassType *object_ptr) { 00336 // fix warning ISO C++ forbids casting from pointer-to-object 00337 // to pointer to function 00338 union { 00339 void* v_; 00340 DestroyObjectFunction* f_; 00341 } Cast; 00342 Cast.v_ = get_destroy_function(); 00343 DestroyObjectFunction *destroy_func = Cast.f_; 00344 if (destroy_func == NULL) 00345 BOOST_THROW_EXCEPTION( error::plugin_undefined() ); 00346 destroy_func(object_ptr); 00347 } 00348 }; 00349 00350 00354 template <typename InterfaceClassType> 00355 class plugin_instance_ptr : 00356 private boost::noncopyable 00357 { 00358 public: 00359 00361 plugin_instance_ptr(void) : m_instance_ptr(NULL) {} 00362 00364 virtual ~plugin_instance_ptr() { reset(); } 00365 00367 inline void reset(void) { 00368 if (m_instance_ptr) { 00369 m_plugin_ptr.destroy(m_instance_ptr); 00370 } 00371 } 00372 00374 inline void create(const std::string& plugin_type) { 00375 reset(); 00376 m_plugin_ptr.open(plugin_type); 00377 m_instance_ptr = m_plugin_ptr.create(); 00378 } 00379 00381 inline bool empty(void) const { return m_instance_ptr==NULL; } 00382 00384 inline InterfaceClassType *get(void) { return m_instance_ptr; } 00385 00387 inline InterfaceClassType& operator*(void) { return *m_instance_ptr; } 00388 00390 inline const InterfaceClassType& operator*(void) const { return *m_instance_ptr; } 00391 00393 inline InterfaceClassType* operator->(void) { return m_instance_ptr; } 00394 00396 inline const InterfaceClassType* operator->(void) const { return m_instance_ptr; } 00397 00398 00399 protected: 00400 00402 plugin_ptr<InterfaceClassType> m_plugin_ptr; 00403 00405 InterfaceClassType * m_instance_ptr; 00406 }; 00407 00408 00422 #ifdef PION_STATIC_LINKING 00423 00424 #define PION_DECLARE_PLUGIN(plugin_name) \ 00425 class plugin_name; \ 00426 extern "C" plugin_name *pion_create_##plugin_name(void); \ 00427 extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \ 00428 static pion::static_entry_point_helper helper_##plugin_name(#plugin_name, (void*) pion_create_##plugin_name, (void*) pion_destroy_##plugin_name); 00429 00431 class static_entry_point_helper { 00432 public: 00433 static_entry_point_helper(const std::string& name, void *create, void *destroy) 00434 { 00435 pion::plugin::add_static_entry_point(name, create, destroy); 00436 } 00437 }; 00438 00439 #else 00440 00441 #define PION_DECLARE_PLUGIN(plugin_name) 00442 00443 #endif 00444 00445 } // end namespace pion 00446 00447 #endif