plugin.hpp
// ---------------------------------------------------------------------
// pion: a Boost C++ framework for building lightweight HTTP interfaces
// ---------------------------------------------------------------------
// Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//
#ifndef __PION_PLUGIN_HEADER__
#define __PION_PLUGIN_HEADER__
#include <vector>
#include <string>
#include <map>
#include <list>
#include <boost/noncopyable.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/filesystem/path.hpp>
#include <pion/config.hpp>
#include <pion/error.hpp>
namespace pion { // begin namespace pion
class PION_API plugin {
public:
static inline bool find_plugin_file(std::string& path_to_file,
const std::string& name)
{
return find_file(path_to_file, name, PION_PLUGIN_EXTENSION);
}
static inline bool find_config_file(std::string& path_to_file,
const std::string& name)
{
return find_file(path_to_file, name, PION_CONFIG_EXTENSION);
}
static void add_static_entry_point(const std::string& plugin_name,
void *create_func,
void *destroy_func);
static void check_cygwin_path(boost::filesystem::path& final_path,
const std::string& path_string);
static void add_plugin_directory(const std::string& dir);
static void reset_plugin_directories(void);
// default destructor
virtual ~plugin() { release_data(); }
inline bool is_open(void) const { return (m_plugin_data != NULL); }
inline std::string get_plugin_name(void) const {
return (is_open() ? m_plugin_data->m_plugin_name : std::string());
}
static void get_all_plugin_names(std::vector<std::string>& plugin_names);
void open(const std::string& plugin_name);
void open_file(const std::string& plugin_file);
inline void close(void) { release_data(); }
protected:
struct data_type
{
data_type(void)
: m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
m_references(0)
{}
data_type(const std::string& plugin_name)
: m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
m_plugin_name(plugin_name), m_references(0)
{}
data_type(const data_type& p)
: m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func),
m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name),
m_references(p.m_references)
{}
void * m_lib_handle;
void * m_create_func;
void * m_destroy_func;
std::string m_plugin_name;
unsigned long m_references;
};
plugin(void) : m_plugin_data(NULL) {}
plugin(const plugin& p) : m_plugin_data(NULL) { grab_data(p); }
plugin& operator=(const plugin& p) { grab_data(p); return *this; }
inline void *get_create_function(void) {
return (is_open() ? m_plugin_data->m_create_func : NULL);
}
inline void *get_destroy_function(void) {
return (is_open() ? m_plugin_data->m_destroy_func : NULL);
}
void release_data(void);
void grab_data(const plugin& p);
private:
typedef std::map<std::string, data_type*> map_type;
struct config_type {
std::vector<std::string> m_plugin_dirs;
map_type m_plugin_map;
boost::mutex m_plugin_mutex;
};
static inline config_type& get_plugin_config(void) {
boost::call_once(plugin::create_plugin_config, m_instance_flag);
return *m_config_ptr;
}
static void create_plugin_config(void);
static bool find_file(std::string& path_to_file, const std::string& name,
const std::string& extension);
static bool check_for_file(std::string& final_path, const std::string& start_path,
const std::string& name, const std::string& extension);
static void open_plugin(const std::string& plugin_file,
data_type& plugin_data);
static std::string get_plugin_name(const std::string& plugin_file);
static void *load_dynamic_library(const std::string& plugin_file);
static void close_dynamic_library(void *lib_handle);
static void *get_library_symbol(void *lib_handle, const std::string& symbol);
static const std::string PION_PLUGIN_CREATE;
static const std::string PION_PLUGIN_DESTROY;
static const std::string PION_PLUGIN_EXTENSION;
static const std::string PION_CONFIG_EXTENSION;
static boost::once_flag m_instance_flag;
static config_type * m_config_ptr;
data_type * m_plugin_data;
};
template <typename InterfaceClassType>
class plugin_ptr :
public plugin
{
protected:
typedef InterfaceClassType* CreateObjectFunction(void);
typedef void DestroyObjectFunction(InterfaceClassType*);
public:
plugin_ptr(void) : plugin() {}
virtual ~plugin_ptr() {}
plugin_ptr(const plugin_ptr& p) : plugin(p) {}
plugin_ptr& operator=(const plugin_ptr& p) { grab_data(p); return *this; }
inline InterfaceClassType *create(void) {
CreateObjectFunction *create_func =
(CreateObjectFunction*)(get_create_function());
if (create_func == NULL)
BOOST_THROW_EXCEPTION( error::plugin_undefined() );
return create_func();
}
inline void destroy(InterfaceClassType *object_ptr) {
// fix warning ISO C++ forbids casting from pointer-to-object
// to pointer to function
union {
void* v_;
DestroyObjectFunction* f_;
} Cast;
Cast.v_ = get_destroy_function();
DestroyObjectFunction *destroy_func = Cast.f_;
if (destroy_func == NULL)
BOOST_THROW_EXCEPTION( error::plugin_undefined() );
destroy_func(object_ptr);
}
};
template <typename InterfaceClassType>
class plugin_instance_ptr :
private boost::noncopyable
{
public:
plugin_instance_ptr(void) : m_instance_ptr(NULL) {}
virtual ~plugin_instance_ptr() { reset(); }
inline void reset(void) {
if (m_instance_ptr) {
m_plugin_ptr.destroy(m_instance_ptr);
}
}
inline void create(const std::string& plugin_type) {
reset();
m_plugin_ptr.open(plugin_type);
m_instance_ptr = m_plugin_ptr.create();
}
inline bool empty(void) const { return m_instance_ptr==NULL; }
inline InterfaceClassType *get(void) { return m_instance_ptr; }
inline InterfaceClassType& operator*(void) { return *m_instance_ptr; }
inline const InterfaceClassType& operator*(void) const { return *m_instance_ptr; }
inline InterfaceClassType* operator->(void) { return m_instance_ptr; }
inline const InterfaceClassType* operator->(void) const { return m_instance_ptr; }
protected:
plugin_ptr<InterfaceClassType> m_plugin_ptr;
InterfaceClassType * m_instance_ptr;
};
#ifdef PION_STATIC_LINKING
#define PION_DECLARE_PLUGIN(plugin_name) \
class plugin_name; \
extern "C" plugin_name *pion_create_##plugin_name(void); \
extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \
static pion::static_entry_point_helper helper_##plugin_name(#plugin_name, (void*) pion_create_##plugin_name, (void*) pion_destroy_##plugin_name);
class static_entry_point_helper {
public:
static_entry_point_helper(const std::string& name, void *create, void *destroy)
{
pion::plugin::add_static_entry_point(name, create, destroy);
}
};
#else
#define PION_DECLARE_PLUGIN(plugin_name)
#endif
} // end namespace pion
#endif
pion::plugin::find_config_file
static bool find_config_file(std::string &path_to_file, const std::string &name)
Definition: plugin.hpp:53
pion::plugin::data_type::m_lib_handle
void * m_lib_handle
symbol library loaded from a shared object file
Definition: plugin.hpp:157
pion::plugin_ptr::destroy
void destroy(InterfaceClassType *object_ptr)
destroys an instance of the plug-in object
Definition: plugin.hpp:335
pion::plugin_instance_ptr::empty
bool empty(void) const
returns true if pointer is empty
Definition: plugin.hpp:381
pion::plugin_ptr::DestroyObjectFunction
void DestroyObjectFunction(InterfaceClassType *)
data type for a function that is used to destroy object instances
Definition: plugin.hpp:310
pion::plugin_instance_ptr::operator->
const InterfaceClassType * operator->(void) const
return a const reference to the instance
Definition: plugin.hpp:396
pion::plugin_ptr
Definition: plugin.hpp:301
pion::plugin::data_type::m_create_func
void * m_create_func
function used to create instances of the plug-in object
Definition: plugin.hpp:160
pion::plugin::find_plugin_file
static bool find_plugin_file(std::string &path_to_file, const std::string &name)
Definition: plugin.hpp:40
pion::plugin_instance_ptr::m_plugin_ptr
plugin_ptr< InterfaceClassType > m_plugin_ptr
smart pointer that manages the plugin&#39;s dynamic object code
Definition: plugin.hpp:402
pion::plugin::data_type::m_plugin_name
std::string m_plugin_name
the name of the plugin (must be unique per process)
Definition: plugin.hpp:166
pion::plugin_instance_ptr::m_instance_ptr
InterfaceClassType * m_instance_ptr
raw pointer to the plugin instance
Definition: plugin.hpp:405
pion::plugin::data_type::m_destroy_func
void * m_destroy_func
function used to destroy instances of the plug-in object
Definition: plugin.hpp:163
pion::plugin_instance_ptr::reset
void reset(void)
reset the instance pointer
Definition: plugin.hpp:367
pion::plugin::plugin
plugin(const plugin &p)
copy constructor
Definition: plugin.hpp:177
pion::plugin::get_destroy_function
void * get_destroy_function(void)
returns a pointer to the plug-in&#39;s "destroy object" function
Definition: plugin.hpp:188
pion::plugin::close
void close(void)
closes plug-in library
Definition: plugin.hpp:132
pion::plugin_instance_ptr::operator->
InterfaceClassType * operator->(void)
return a reference to the instance
Definition: plugin.hpp:393
pion::plugin
Definition: plugin.hpp:30
pion::error::plugin_undefined
exception thrown if a plugin has an undefined state
Definition: error.hpp:202
pion::plugin::get_plugin_name
std::string get_plugin_name(void) const
returns the name of the plugin that is currently open
Definition: plugin.hpp:96
pion::plugin_ptr::create
InterfaceClassType * create(void)
creates a new instance of the plug-in object
Definition: plugin.hpp:326
pion::plugin_ptr::plugin_ptr
plugin_ptr(void)
default constructor & destructor
Definition: plugin.hpp:316
pion::plugin_instance_ptr::operator*
InterfaceClassType & operator*(void)
return a reference to the instance
Definition: plugin.hpp:387
pion::plugin::get_create_function
void * get_create_function(void)
returns a pointer to the plug-in&#39;s "create object" function
Definition: plugin.hpp:183
pion::plugin::data_type::data_type
data_type(void)
default constructors for convenience
Definition: plugin.hpp:142
pion::plugin::data_type::m_references
unsigned long m_references
number of references to this class
Definition: plugin.hpp:169
pion::plugin_instance_ptr::~plugin_instance_ptr
virtual ~plugin_instance_ptr()
virtual destructor / may be extended
Definition: plugin.hpp:364
pion::plugin_instance_ptr::operator*
const InterfaceClassType & operator*(void) const
return a const reference to the instance
Definition: plugin.hpp:390
pion::plugin::is_open
bool is_open(void) const
returns true if a shared library is loaded/open
Definition: plugin.hpp:93
pion::plugin::plugin
plugin(void)
default constructor is private (use plugin_ptr class to create objects)
Definition: plugin.hpp:174
pion::plugin_ptr::CreateObjectFunction
InterfaceClassType * CreateObjectFunction(void)
data type for a function that is used to create object instances
Definition: plugin.hpp:307
pion::plugin_instance_ptr::plugin_instance_ptr
plugin_instance_ptr(void)
default constructor & destructor
Definition: plugin.hpp:361
pion
Definition: admin_rights.hpp:19
pion::plugin_instance_ptr
Definition: plugin.hpp:355
pion::plugin_instance_ptr::create
void create(const std::string &plugin_type)
create a new instance of the given plugin_type
Definition: plugin.hpp:374
pion::plugin::add_static_entry_point
static void add_static_entry_point(const std::string &plugin_name, void *create_func, void *destroy_func)
Definition: plugin.cpp:390
pion::plugin::operator=
plugin & operator=(const plugin &p)
assignment operator
Definition: plugin.hpp:180
pion::plugin::data_type
Definition: plugin.hpp:139
pion::plugin_ptr::plugin_ptr
plugin_ptr(const plugin_ptr &p)
copy constructor
Definition: plugin.hpp:320
pion::plugin_ptr::operator=
plugin_ptr & operator=(const plugin_ptr &p)
assignment operator
Definition: plugin.hpp:323