pion  5.0.6
plugin.hpp
1 // ---------------------------------------------------------------------
2 // pion: a Boost C++ framework for building lightweight HTTP interfaces
3 // ---------------------------------------------------------------------
4 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #ifndef __PION_PLUGIN_HEADER__
11 #define __PION_PLUGIN_HEADER__
12 
13 #include <vector>
14 #include <string>
15 #include <map>
16 #include <list>
17 #include <boost/noncopyable.hpp>
18 #include <boost/thread/once.hpp>
19 #include <boost/thread/mutex.hpp>
20 #include <boost/filesystem/path.hpp>
21 #include <pion/config.hpp>
22 #include <pion/error.hpp>
23 
24 
25 namespace pion { // begin namespace pion
26 
30 class PION_API plugin {
31 public:
32 
40  static inline bool find_plugin_file(std::string& path_to_file,
41  const std::string& name)
42  {
43  return find_file(path_to_file, name, PION_PLUGIN_EXTENSION);
44  }
45 
53  static inline bool find_config_file(std::string& path_to_file,
54  const std::string& name)
55  {
56  return find_file(path_to_file, name, PION_CONFIG_EXTENSION);
57  }
58 
67  static void add_static_entry_point(const std::string& plugin_name,
68  void *create_func,
69  void *destroy_func);
70 
79  static void check_cygwin_path(boost::filesystem::path& final_path,
80  const std::string& path_string);
81 
83  static void add_plugin_directory(const std::string& dir);
84 
86  static void reset_plugin_directories(void);
87 
88 
89  // default destructor
90  virtual ~plugin() { release_data(); }
91 
93  inline bool is_open(void) const { return (m_plugin_data != NULL); }
94 
96  inline std::string get_plugin_name(void) const {
97  return (is_open() ? m_plugin_data->m_plugin_name : std::string());
98  }
99 
101  static void get_all_plugin_names(std::vector<std::string>& plugin_names);
102 
115  void open(const std::string& plugin_name);
116 
129  void open_file(const std::string& plugin_file);
130 
132  inline void close(void) { release_data(); }
133 
134 protected:
135 
139  struct data_type
140  {
142  data_type(void)
143  : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
144  m_references(0)
145  {}
146  data_type(const std::string& plugin_name)
147  : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
148  m_plugin_name(plugin_name), m_references(0)
149  {}
150  data_type(const data_type& p)
151  : m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func),
152  m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name),
153  m_references(p.m_references)
154  {}
155 
157  void * m_lib_handle;
158 
161 
164 
166  std::string m_plugin_name;
167 
169  unsigned long m_references;
170  };
171 
172 
174  plugin(void) : m_plugin_data(NULL) {}
175 
177  plugin(const plugin& p) : m_plugin_data(NULL) { grab_data(p); }
178 
180  plugin& operator=(const plugin& p) { grab_data(p); return *this; }
181 
183  inline void *get_create_function(void) {
184  return (is_open() ? m_plugin_data->m_create_func : NULL);
185  }
186 
188  inline void *get_destroy_function(void) {
189  return (is_open() ? m_plugin_data->m_destroy_func : NULL);
190  }
191 
193  void release_data(void);
194 
196  void grab_data(const plugin& p);
197 
198 
199 private:
200 
202  typedef std::map<std::string, data_type*> map_type;
203 
205  struct config_type {
207  std::vector<std::string> m_plugin_dirs;
208 
210  map_type m_plugin_map;
211 
213  boost::mutex m_plugin_mutex;
214  };
215 
216 
218  static inline config_type& get_plugin_config(void) {
219  boost::call_once(plugin::create_plugin_config, m_instance_flag);
220  return *m_config_ptr;
221  }
222 
224  static void create_plugin_config(void);
225 
235  static bool find_file(std::string& path_to_file, const std::string& name,
236  const std::string& extension);
237 
248  static bool check_for_file(std::string& final_path, const std::string& start_path,
249  const std::string& name, const std::string& extension);
250 
257  static void open_plugin(const std::string& plugin_file,
258  data_type& plugin_data);
259 
261  static std::string get_plugin_name(const std::string& plugin_file);
262 
264  static void *load_dynamic_library(const std::string& plugin_file);
265 
267  static void close_dynamic_library(void *lib_handle);
268 
270  static void *get_library_symbol(void *lib_handle, const std::string& symbol);
271 
272 
274  static const std::string PION_PLUGIN_CREATE;
275 
277  static const std::string PION_PLUGIN_DESTROY;
278 
280  static const std::string PION_PLUGIN_EXTENSION;
281 
283  static const std::string PION_CONFIG_EXTENSION;
284 
286  static boost::once_flag m_instance_flag;
287 
289  static config_type * m_config_ptr;
290 
292  data_type * m_plugin_data;
293 };
294 
295 
300 template <typename InterfaceClassType>
301 class plugin_ptr :
302  public plugin
303 {
304 protected:
305 
307  typedef InterfaceClassType* CreateObjectFunction(void);
308 
310  typedef void DestroyObjectFunction(InterfaceClassType*);
311 
312 
313 public:
314 
316  plugin_ptr(void) : plugin() {}
317  virtual ~plugin_ptr() {}
318 
320  plugin_ptr(const plugin_ptr& p) : plugin(p) {}
321 
323  plugin_ptr& operator=(const plugin_ptr& p) { grab_data(p); return *this; }
324 
326  inline InterfaceClassType *create(void) {
327  CreateObjectFunction *create_func =
329  if (create_func == NULL)
330  BOOST_THROW_EXCEPTION( error::plugin_undefined() );
331  return create_func();
332  }
333 
335  inline void destroy(InterfaceClassType *object_ptr) {
336  // fix warning ISO C++ forbids casting from pointer-to-object
337  // to pointer to function
338  union {
339  void* v_;
341  } Cast;
342  Cast.v_ = get_destroy_function();
343  DestroyObjectFunction *destroy_func = Cast.f_;
344  if (destroy_func == NULL)
345  BOOST_THROW_EXCEPTION( error::plugin_undefined() );
346  destroy_func(object_ptr);
347  }
348 };
349 
350 
354 template <typename InterfaceClassType>
356  private boost::noncopyable
357 {
358 public:
359 
362 
364  virtual ~plugin_instance_ptr() { reset(); }
365 
367  inline void reset(void) {
368  if (m_instance_ptr) {
369  m_plugin_ptr.destroy(m_instance_ptr);
370  }
371  }
372 
374  inline void create(const std::string& plugin_type) {
375  reset();
376  m_plugin_ptr.open(plugin_type);
377  m_instance_ptr = m_plugin_ptr.create();
378  }
379 
381  inline bool empty(void) const { return m_instance_ptr==NULL; }
382 
384  inline InterfaceClassType *get(void) { return m_instance_ptr; }
385 
387  inline InterfaceClassType& operator*(void) { return *m_instance_ptr; }
388 
390  inline const InterfaceClassType& operator*(void) const { return *m_instance_ptr; }
391 
393  inline InterfaceClassType* operator->(void) { return m_instance_ptr; }
394 
396  inline const InterfaceClassType* operator->(void) const { return m_instance_ptr; }
397 
398 
399 protected:
400 
403 
405  InterfaceClassType * m_instance_ptr;
406 };
407 
408 
422 #ifdef PION_STATIC_LINKING
423 
424 #define PION_DECLARE_PLUGIN(plugin_name) \
425  class plugin_name; \
426  extern "C" plugin_name *pion_create_##plugin_name(void); \
427  extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \
428  static pion::static_entry_point_helper helper_##plugin_name(#plugin_name, (void*) pion_create_##plugin_name, (void*) pion_destroy_##plugin_name);
429 
431 class static_entry_point_helper {
432 public:
433  static_entry_point_helper(const std::string& name, void *create, void *destroy)
434  {
435  pion::plugin::add_static_entry_point(name, create, destroy);
436  }
437 };
438 
439 #else
440 
441 #define PION_DECLARE_PLUGIN(plugin_name)
442 
443 #endif
444 
445 } // end namespace pion
446 
447 #endif
bool is_open(void) const
returns true if a shared library is loaded/open
Definition: plugin.hpp:93
void grab_data(const plugin &p)
grabs a reference to another plug-in's shared library symbols
Definition: plugin.cpp:165
static bool find_config_file(std::string &path_to_file, const std::string &name)
Definition: plugin.hpp:53
void * m_lib_handle
symbol library loaded from a shared object file
Definition: plugin.hpp:157
void destroy(InterfaceClassType *object_ptr)
destroys an instance of the plug-in object
Definition: plugin.hpp:335
std::string get_plugin_name(void) const
returns the name of the plugin that is currently open
Definition: plugin.hpp:96
void DestroyObjectFunction(InterfaceClassType *)
data type for a function that is used to destroy object instances
Definition: plugin.hpp:310
const InterfaceClassType & operator*(void) const
return a const reference to the instance
Definition: plugin.hpp:390
bool empty(void) const
returns true if pointer is empty
Definition: plugin.hpp:381
void * m_create_func
function used to create instances of the plug-in object
Definition: plugin.hpp:160
static bool find_plugin_file(std::string &path_to_file, const std::string &name)
Definition: plugin.hpp:40
plugin_ptr< InterfaceClassType > m_plugin_ptr
smart pointer that manages the plugin's dynamic object code
Definition: plugin.hpp:402
std::string m_plugin_name
the name of the plugin (must be unique per process)
Definition: plugin.hpp:166
InterfaceClassType * m_instance_ptr
raw pointer to the plugin instance
Definition: plugin.hpp:405
void * m_destroy_func
function used to destroy instances of the plug-in object
Definition: plugin.hpp:163
void reset(void)
reset the instance pointer
Definition: plugin.hpp:367
plugin(const plugin &p)
copy constructor
Definition: plugin.hpp:177
void * get_destroy_function(void)
returns a pointer to the plug-in's "destroy object" function
Definition: plugin.hpp:188
void close(void)
closes plug-in library
Definition: plugin.hpp:132
InterfaceClassType * operator->(void)
return a reference to the instance
Definition: plugin.hpp:393
exception thrown if a plugin has an undefined state
Definition: error.hpp:202
InterfaceClassType * create(void)
creates a new instance of the plug-in object
Definition: plugin.hpp:326
plugin_ptr(void)
default constructor & destructor
Definition: plugin.hpp:316
InterfaceClassType & operator*(void)
return a reference to the instance
Definition: plugin.hpp:387
void * get_create_function(void)
returns a pointer to the plug-in's "create object" function
Definition: plugin.hpp:183
data_type(void)
default constructors for convenience
Definition: plugin.hpp:142
unsigned long m_references
number of references to this class
Definition: plugin.hpp:169
virtual ~plugin_instance_ptr()
virtual destructor / may be extended
Definition: plugin.hpp:364
plugin(void)
default constructor is private (use plugin_ptr class to create objects)
Definition: plugin.hpp:174
InterfaceClassType * CreateObjectFunction(void)
data type for a function that is used to create object instances
Definition: plugin.hpp:307
plugin_instance_ptr(void)
default constructor & destructor
Definition: plugin.hpp:361
void create(const std::string &plugin_type)
create a new instance of the given plugin_type
Definition: plugin.hpp:374
static void add_static_entry_point(const std::string &plugin_name, void *create_func, void *destroy_func)
Definition: plugin.cpp:390
plugin & operator=(const plugin &p)
assignment operator
Definition: plugin.hpp:180
plugin_ptr(const plugin_ptr &p)
copy constructor
Definition: plugin.hpp:320
const InterfaceClassType * operator->(void) const
return a const reference to the instance
Definition: plugin.hpp:396
plugin_ptr & operator=(const plugin_ptr &p)
assignment operator
Definition: plugin.hpp:323