10 #include <boost/filesystem.hpp>
11 #include <boost/filesystem/operations.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <pion/PionConfig.hpp>
14 #include <pion/PionPlugin.hpp>
27 const std::string PionPlugin::PION_PLUGIN_CREATE(
"pion_create_");
28 const std::string PionPlugin::PION_PLUGIN_DESTROY(
"pion_destroy_");
30 const std::string PionPlugin::PION_PLUGIN_EXTENSION(
".dll");
32 const std::string PionPlugin::PION_PLUGIN_EXTENSION(
".so");
34 const std::string PionPlugin::PION_CONFIG_EXTENSION(
".conf");
35 std::vector<std::string> PionPlugin::m_plugin_dirs;
36 PionPlugin::PluginMap PionPlugin::m_plugin_map;
37 boost::mutex PionPlugin::m_plugin_mutex;
38 PionPlugin::StaticEntryPointList *PionPlugin::m_entry_points_ptr = NULL;
44 const std::string& start_path)
46 #if defined(PION_WIN32) && defined(PION_CYGWIN_DIRECTORY)
48 if (! final_path.is_complete() && final_path.has_root_directory()) {
49 final_path = boost::filesystem::path(std::string(PION_CYGWIN_DIRECTORY) + start_path);
56 boost::filesystem::path plugin_path = boost::filesystem::system_complete(dir);
58 if (! boost::filesystem::exists(plugin_path) )
60 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
61 m_plugin_dirs.push_back(plugin_path.string());
66 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
67 m_plugin_dirs.clear();
72 std::string plugin_file;
88 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
89 PluginMap::iterator itr = m_plugin_map.find(plugin_data.
m_plugin_name);
90 if (itr == m_plugin_map.end()) {
94 openPlugin(plugin_file, plugin_data);
98 m_plugin_map.insert( std::make_pair(m_plugin_data->
m_plugin_name,
102 m_plugin_data = itr->second;
116 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
117 PluginMap::iterator itr = m_plugin_map.find(plugin_name);
118 if (itr == m_plugin_map.end()) {
126 m_plugin_map.insert(std::make_pair(m_plugin_data->
m_plugin_name,
130 m_plugin_data = itr->second;
139 if (m_plugin_data != NULL) {
140 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
142 if (m_plugin_data != NULL && --m_plugin_data->
m_references == 0) {
149 PluginMap::iterator itr = m_plugin_map.find(m_plugin_data->
m_plugin_name);
151 if (itr != m_plugin_map.end())
152 m_plugin_map.erase(itr);
155 delete m_plugin_data;
157 m_plugin_data = NULL;
164 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
166 if (m_plugin_data != NULL) {
171 bool PionPlugin::findFile(std::string& path_to_file,
const std::string& name,
172 const std::string& extension)
175 if (checkForFile(path_to_file, name,
"", extension))
179 boost::mutex::scoped_lock plugin_lock(m_plugin_mutex);
180 for (std::vector<std::string>::iterator i = m_plugin_dirs.begin();
181 i != m_plugin_dirs.end(); ++i)
183 if (checkForFile(path_to_file, *i, name, extension))
191 bool PionPlugin::checkForFile(std::string& final_path,
const std::string& start_path,
192 const std::string& name,
const std::string& extension)
195 boost::filesystem::path cygwin_safe_path(start_path);
197 boost::filesystem::path test_path(cygwin_safe_path);
206 if (boost::filesystem::is_regular(test_path)) {
207 final_path = test_path.string();
215 test_path = boost::filesystem::path(start_path + extension);
220 test_path = cygwin_safe_path /
221 boost::filesystem::path(name + extension);
227 if (boost::filesystem::is_regular(test_path)) {
228 final_path = test_path.string();
237 void PionPlugin::openPlugin(
const std::string& plugin_file,
238 PionPluginData& plugin_data)
245 plugin_data.m_lib_handle = loadDynamicLibrary(plugin_file.c_str());
246 if (plugin_data.m_lib_handle == NULL) {
248 const char *error_msg = dlerror();
249 if (error_msg != NULL) {
250 std::string error_str(plugin_file);
252 error_str += error_msg;
254 throw OpenPluginException(error_str);
257 throw OpenPluginException(plugin_file);
261 plugin_data.m_create_func =
262 getLibrarySymbol(plugin_data.m_lib_handle,
263 PION_PLUGIN_CREATE + plugin_data.m_plugin_name);
264 if (plugin_data.m_create_func == NULL) {
265 closeDynamicLibrary(plugin_data.m_lib_handle);
266 throw PluginMissingCreateException(plugin_file);
270 plugin_data.m_destroy_func =
271 getLibrarySymbol(plugin_data.m_lib_handle,
272 PION_PLUGIN_DESTROY + plugin_data.m_plugin_name);
273 if (plugin_data.m_destroy_func == NULL) {
274 closeDynamicLibrary(plugin_data.m_lib_handle);
275 throw PluginMissingDestroyException(plugin_file);
281 return boost::filesystem::basename(boost::filesystem::path(plugin_file));
287 std::vector<std::string>::iterator it;
288 for (it = m_plugin_dirs.begin(); it != m_plugin_dirs.end(); ++it) {
290 boost::filesystem::directory_iterator end;
291 for (boost::filesystem::directory_iterator it2(*it); it2 != end; ++it2) {
292 if (boost::filesystem::is_regular(*it2)) {
293 if (boost::filesystem::extension(it2->path()) == PionPlugin::PION_PLUGIN_EXTENSION) {
301 void *PionPlugin::loadDynamicLibrary(
const std::string& plugin_file)
305 return LoadLibraryA(plugin_file.c_str());
307 return LoadLibrary(plugin_file.c_str());
312 const boost::filesystem::path full_path = boost::filesystem::absolute(plugin_file);
316 return dlopen(full_path.string().c_str(), RTLD_LAZY | RTLD_GLOBAL);
320 void PionPlugin::closeDynamicLibrary(
void *lib_handle)
338 void *PionPlugin::getLibrarySymbol(
void *lib_handle,
const std::string& symbol)
341 return (
void*)GetProcAddress((HINSTANCE) lib_handle, symbol.c_str());
343 return dlsym(lib_handle, symbol.c_str());
352 if (m_entry_points_ptr == NULL || m_entry_points_ptr->empty())
356 for (std::list<StaticEntryPoint>::const_iterator i = m_entry_points_ptr->begin();
357 i != m_entry_points_ptr->end(); ++i) {
358 if (i->m_plugin_name==plugin_name) {
359 *create_func = i->m_create_func;
360 *destroy_func = i->m_destroy_func;
372 static boost::mutex entrypoint_mutex;
373 boost::mutex::scoped_lock entrypoint_lock(entrypoint_mutex);
376 if (m_entry_points_ptr == NULL)
377 m_entry_points_ptr =
new StaticEntryPointList;
380 m_entry_points_ptr->push_back(StaticEntryPoint(plugin_name, create_func, destroy_func));
void openFile(const std::string &plugin_file)
exception thrown if the plug-in directory does not exist
void * m_lib_handle
symbol library loaded from a shared object file
static bool findStaticEntryPoint(const std::string &plugin_name, void **create_func, void **destroy_func)
void * m_create_func
function used to create instances of the plug-in object
std::string getPluginName(void) const
returns the name of the plugin that is currently open
static void checkCygwinPath(boost::filesystem::path &final_path, const std::string &path_string)
void grabData(const PionPlugin &p)
grabs a reference to another plug-in's shared library symbols
static void getAllPluginNames(std::vector< std::string > &plugin_names)
returns a list of all Plugins found in all Plugin directories
void open(const std::string &plugin_name)
void openStaticLinked(const std::string &plugin_name, void *create_func, void *destroy_func)
void releaseData(void)
releases the plug-in's shared library symbols
static bool findPluginFile(std::string &path_to_file, const std::string &name)
static void addStaticEntryPoint(const std::string &plugin_name, void *create_func, void *destroy_func)
exception thrown if the plug-in file cannot be found
static void addPluginDirectory(const std::string &dir)
appends a directory to the plug-in search path
the following enables use of the lock-free cache
static void resetPluginDirectories(void)
clears all directories from the plug-in search path
void * m_destroy_func
function used to destroy instances of the plug-in object
unsigned long m_references
number of references to this class
std::string m_plugin_name
the name of the plugin (must be unique per process)