10 #include <boost/filesystem.hpp>
11 #include <boost/filesystem/operations.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <pion/config.hpp>
14 #include <pion/error.hpp>
15 #include <pion/plugin.hpp>
28 const std::string plugin::PION_PLUGIN_CREATE(
"pion_create_");
29 const std::string plugin::PION_PLUGIN_DESTROY(
"pion_destroy_");
31 const std::string plugin::PION_PLUGIN_EXTENSION(
".dll");
33 const std::string plugin::PION_PLUGIN_EXTENSION(
".so");
35 const std::string plugin::PION_CONFIG_EXTENSION(
".conf");
36 boost::once_flag plugin::m_instance_flag = BOOST_ONCE_INIT;
37 plugin::config_type *plugin::m_config_ptr = NULL;
42 void plugin::create_plugin_config(
void)
44 static config_type UNIQUE_PION_PLUGIN_CONFIG;
45 m_config_ptr = &UNIQUE_PION_PLUGIN_CONFIG;
49 const std::string& start_path)
51 #if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY)
53 if (! final_path.is_complete() && final_path.has_root_directory()) {
54 final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
61 boost::filesystem::path plugin_path = boost::filesystem::system_complete(dir);
63 if (! boost::filesystem::exists(plugin_path) )
65 config_type& cfg = get_plugin_config();
66 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
67 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
68 cfg.m_plugin_dirs.push_back(plugin_path.string());
70 cfg.m_plugin_dirs.push_back(plugin_path.directory_string());
77 config_type& cfg = get_plugin_config();
78 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
79 cfg.m_plugin_dirs.clear();
86 config_type& cfg = get_plugin_config();
87 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
88 map_type::iterator itr = cfg.m_plugin_map.find(plugin_name);
89 if (itr != cfg.m_plugin_map.end()) {
91 m_plugin_data = itr->second;
98 std::string plugin_file;
114 config_type& cfg = get_plugin_config();
115 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
116 map_type::iterator itr = cfg.m_plugin_map.find(plugin_data.
m_plugin_name);
117 if (itr == cfg.m_plugin_map.end()) {
121 open_plugin(plugin_file, plugin_data);
124 m_plugin_data =
new data_type(plugin_data);
125 cfg.m_plugin_map.insert( std::make_pair(m_plugin_data->
m_plugin_name,
129 m_plugin_data = itr->second;
138 if (m_plugin_data != NULL) {
139 config_type& cfg = get_plugin_config();
140 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
142 if (m_plugin_data != NULL && --m_plugin_data->
m_references == 0) {
152 map_type::iterator itr = cfg.m_plugin_map.find(m_plugin_data->
m_plugin_name);
154 if (itr != cfg.m_plugin_map.end())
155 cfg.m_plugin_map.erase(itr);
158 delete m_plugin_data;
161 m_plugin_data = NULL;
168 config_type& cfg = get_plugin_config();
169 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
170 m_plugin_data =
const_cast<data_type*
>(p.m_plugin_data);
171 if (m_plugin_data != NULL) {
176 bool plugin::find_file(std::string& path_to_file,
const std::string& name,
177 const std::string& extension)
180 if (check_for_file(path_to_file, name,
"", extension))
184 config_type& cfg = get_plugin_config();
185 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
186 for (std::vector<std::string>::iterator i = cfg.m_plugin_dirs.begin();
187 i != cfg.m_plugin_dirs.end(); ++i)
189 if (check_for_file(path_to_file, *i, name, extension))
197 bool plugin::check_for_file(std::string& final_path,
const std::string& start_path,
198 const std::string& name,
const std::string& extension)
201 boost::filesystem::path cygwin_safe_path(start_path);
203 boost::filesystem::path test_path(cygwin_safe_path);
212 if (boost::filesystem::is_regular(test_path)) {
213 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
214 final_path = test_path.string();
216 final_path = test_path.file_string();
225 test_path = boost::filesystem::path(start_path + extension);
230 test_path = cygwin_safe_path /
231 boost::filesystem::path(name + extension);
237 if (boost::filesystem::is_regular(test_path)) {
238 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
239 final_path = test_path.string();
241 final_path = test_path.file_string();
251 void plugin::open_plugin(
const std::string& plugin_file,
252 data_type& plugin_data)
259 plugin_data.m_lib_handle = load_dynamic_library(plugin_file.c_str());
260 if (plugin_data.m_lib_handle == NULL) {
262 const char *error_msg = dlerror();
263 if (error_msg != NULL) {
264 std::string error_str(plugin_file);
266 error_str += error_msg;
268 BOOST_THROW_EXCEPTION( error::open_plugin()
269 << error::errinfo_plugin_name(plugin_data.m_plugin_name)
270 << error::errinfo_message(error_str) );
273 BOOST_THROW_EXCEPTION( error::open_plugin()
274 << error::errinfo_plugin_name(plugin_data.m_plugin_name) );
278 plugin_data.m_create_func =
279 get_library_symbol(plugin_data.m_lib_handle,
280 PION_PLUGIN_CREATE + plugin_data.m_plugin_name);
281 if (plugin_data.m_create_func == NULL) {
282 close_dynamic_library(plugin_data.m_lib_handle);
283 BOOST_THROW_EXCEPTION( error::plugin_missing_symbol()
284 << error::errinfo_plugin_name(plugin_data.m_plugin_name)
285 << error::errinfo_symbol_name(PION_PLUGIN_CREATE + plugin_data.m_plugin_name) );
289 plugin_data.m_destroy_func =
290 get_library_symbol(plugin_data.m_lib_handle,
291 PION_PLUGIN_DESTROY + plugin_data.m_plugin_name);
292 if (plugin_data.m_destroy_func == NULL) {
293 close_dynamic_library(plugin_data.m_lib_handle);
294 BOOST_THROW_EXCEPTION( error::plugin_missing_symbol()
295 << error::errinfo_plugin_name(plugin_data.m_plugin_name)
296 << error::errinfo_symbol_name(PION_PLUGIN_DESTROY + plugin_data.m_plugin_name) );
302 return boost::filesystem::basename(boost::filesystem::path(plugin_file));
308 std::vector<std::string>::iterator it;
309 config_type& cfg = get_plugin_config();
310 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
311 for (it = cfg.m_plugin_dirs.begin(); it != cfg.m_plugin_dirs.end(); ++it) {
313 boost::filesystem::directory_iterator end;
314 for (boost::filesystem::directory_iterator it2(*it); it2 != end; ++it2) {
315 if (boost::filesystem::is_regular(*it2)) {
316 if (boost::filesystem::extension(it2->path()) == plugin::PION_PLUGIN_EXTENSION) {
317 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
328 for (map_type::const_iterator itr = cfg.m_plugin_map.begin(); itr != cfg.m_plugin_map.end(); ++itr) {
329 const data_type& plugin_data = *(itr->second);
336 void *plugin::load_dynamic_library(
const std::string& plugin_file)
340 return LoadLibraryA(plugin_file.c_str());
342 return LoadLibrary(plugin_file.c_str());
347 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
348 const boost::filesystem::path full_path = boost::filesystem::absolute(plugin_file);
350 const boost::filesystem::path full_path = boost::filesystem::complete(plugin_file);
355 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
356 return dlopen(full_path.string().c_str(), RTLD_LAZY | RTLD_GLOBAL);
358 return dlopen(full_path.file_string().c_str(), RTLD_LAZY | RTLD_GLOBAL);
363 void plugin::close_dynamic_library(
void *lib_handle)
381 void *plugin::get_library_symbol(
void *lib_handle,
const std::string& symbol)
384 return (
void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
386 return dlsym(lib_handle, symbol.c_str());
395 config_type& cfg = get_plugin_config();
396 boost::mutex::scoped_lock plugin_lock(cfg.m_plugin_mutex);
397 map_type::iterator itr = cfg.m_plugin_map.find(plugin_name);
398 if (itr == cfg.m_plugin_map.end()) {
405 cfg.m_plugin_map.insert(std::make_pair(plugin_name, plugin_data));
void open_file(const std::string &plugin_file)
void grab_data(const plugin &p)
grabs a reference to another plug-in's shared library symbols
void * m_lib_handle
symbol library loaded from a shared object file
std::string get_plugin_name(void) const
returns the name of the plugin that is currently open
static void add_plugin_directory(const std::string &dir)
appends a directory to the plug-in search path
void release_data(void)
releases the plug-in's shared library symbols
static void reset_plugin_directories(void)
clears all directories from the plug-in search path
void * m_create_func
function used to create instances of the plug-in object
static bool find_plugin_file(std::string &path_to_file, const std::string &name)
std::string m_plugin_name
the name of the plugin (must be unique per process)
exception thrown if a required directory is not found
void * m_destroy_func
function used to destroy instances of the plug-in object
static void check_cygwin_path(boost::filesystem::path &final_path, const std::string &path_string)
unsigned long m_references
number of references to this class
exception thrown if a plugin cannot be found
void open(const std::string &plugin_name)
static void add_static_entry_point(const std::string &plugin_name, void *create_func, void *destroy_func)
static void get_all_plugin_names(std::vector< std::string > &plugin_names)
returns a list of all Plugins found in all Plugin directories