Commit 5cec7153 authored by Emmanuel Milou's avatar Emmanuel Milou

Add header files

parent 0953d8a9
......@@ -8,5 +8,5 @@ SUBDIRS=test
libplugin_la_SOURCES = \
pluginmanager.cpp \
plugin.cpp
librarymanager.cpp
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "librarymanager.h"
LibraryManager::LibraryManager (const std::string &filename)
: _filename(filename), _handlePtr(NULL)
{
_handlePtr = loadLibrary (filename);
}
LibraryManager::~LibraryManager (void)
{
unloadLibrary ();
}
LibraryManager::LibraryHandle LibraryManager::loadLibrary (const std::string &filename)
{
LibraryHandle pluginHandlePtr = NULL;
const char *error;
_debug("Loading dynamic library %s\n", filename.c_str());
/* Load the library */
pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY );
if( !pluginHandlePtr ) {
error = dlerror();
_debug("Error while opening plug-in: %s\n", error);
return NULL;
}
dlerror();
return pluginHandlePtr;
}
int LibraryManager::unloadLibrary ()
{
if (_handlePtr == NULL)
return 1;
_debug("Unloading dynamic library ...\n");
dlclose( _handlePtr );
if (dlerror())
{
_debug("Error unloading the library : %s\n...", dlerror());
return 1;
}
return 0;
}
int LibraryManager::resolveSymbol (const std::string &symbol, SymbolHandle *symbolPtr)
{
SymbolHandle sy = 0;
if (_handlePtr){
try {
sy = dlsym(_handlePtr, symbol.c_str());
if(sy != NULL) {
*symbolPtr = sy;
return 0;
}
}
catch (...) {}
throw LibraryManagerException ( _filename, symbol, LibraryManagerException::symbolNotFound);
}
else
return 1;
}
/************************************************************************************************/
LibraryManagerException::LibraryManagerException (const std::string &libraryName, const std::string &details, Reason reason) :
_reason (reason), _details (""), std::runtime_error ("")
{
if (_reason == loadingFailed)
_details = "Error when loading " + libraryName + "\n" + details;
else
_details = "Error when resolving symbol " + details + " in " + libraryName;
}
const char* LibraryManagerException::what () const throw()
{
return _details.c_str();
}
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LIBRARY_MANAGER_H
#define LIBRARY_MANAGER_H
#include "dlfcn.h"
#include <stdexcept>
#include "global.h"
class LibraryManager {
public:
typedef void* LibraryHandle;
typedef void* SymbolHandle;
LibraryManager (const std::string &filename);
~LibraryManager (void);
int resolveSymbol (const std::string &symbol, SymbolHandle *ptr);
int unloadLibrary (void);
protected:
LibraryHandle loadLibrary (const std::string &filename);
private:
std::string _filename;
LibraryHandle _handlePtr;
};
class LibraryManagerException : public std::runtime_error {
public:
typedef enum Reason {
loadingFailed = 0,
symbolNotFound
}Reason;
LibraryManagerException (const std::string &libraryName, const std::string &details, Reason reason);
~LibraryManagerException (void) throw() {}
inline Reason getReason (void) { return _reason; }
const char* what () const throw();
private:
Reason _reason;
std::string _details;
};
#endif // LIBRARY_MANAGER_H
#include "plugin.h"
::sflphone::Plugin::Plugin (void *handle, PluginInterface *interface)
:_handlePtr(handle), _interface(interface)
{
}
::sflphone::Plugin::Plugin (PluginInterface *interface)
:_interface(interface)
{
}
::sflphone::Plugin::~Plugin ()
{
}
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PLUGIN_H
#define PLUGIN_H
#include "plugininterface.h"
#include "global.h"
#include "pluginmanager.h"
/*
* @file plugin.h
* @brief Define a plugin object
*/
namespace sflphone {
class Plugin {
class PluginInterface;
public:
Plugin( const std::string &name ){
_name = name;
}
class Plugin {
virtual ~Plugin() {}
public:
inline std::string getPluginName (void) { return _name; }
Plugin (void*, PluginInterface *interface);
Plugin (PluginInterface *interface);
/**
* Return the minimal core version required so that the plugin could work
* @return int The version required
*/
virtual int initFunc (PluginInfo **info) = 0;
~Plugin ();
private:
Plugin &operator =(const Plugin &plugin);
void setName (std::string name);
private:
std::string _name;
int _version_major;
int _version_minor;
int _required;
void *_handlePtr;
PluginInterface *_interface;
std::string _name;
};
typedef Plugin* createFunc (void);
typedef void destroyFunc (Plugin*);
friend class PluginTest;
friend class PluginManager;
};
}
#endif //PLUGIN_H
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <dirent.h>
#include <dlfcn.h>
#include "pluginmanager.h"
::sflphone::PluginManager* ::sflphone::PluginManager::_instance = 0;
PluginManager* PluginManager::_instance = 0;
::sflphone::PluginManager*
::sflphone::PluginManager::instance()
PluginManager*
PluginManager::instance()
{
if(!_instance){
return new PluginManager();
......@@ -14,28 +33,26 @@
return _instance;
}
::sflphone::PluginManager::PluginManager()
:_loadedPlugins()
PluginManager::PluginManager()
:_loadedPlugins()
{
_instance = this;
}
::sflphone::PluginManager::~PluginManager()
PluginManager::~PluginManager()
{
_instance = 0;
}
int
::sflphone::PluginManager::loadPlugins (const std::string &path)
PluginManager::loadPlugins (const std::string &path)
{
std::string pluginDir, current;
::sflphone::PluginInterface *interface;
DIR *dir;
dirent *dirStruct;
int result=0;
void *handle;
createFunc* createPlugin;
LibraryManager *library;
Plugin *plugin;
const std::string pDir = "..";
const std::string cDir = ".";
......@@ -52,19 +69,25 @@
current = dirStruct->d_name;
/* Test if the current item is not the parent or the current directory */
if( current != pDir && current != cDir ){
handle = loadDynamicLibrary( pluginDir + current );
if(instanciatePlugin (handle, &interface) != 0)
/* Load the dynamic library */
library = loadDynamicLibrary( pluginDir + current );
/* Instanciate the plugin object */
if(instanciatePlugin (library, &plugin) != 0)
{
_debug("Error instanciating the plugin ...\n");
return 1;
}
if(registerPlugin (handle, interface) != 0)
/* Regitering the current plugin */
if(registerPlugin (plugin, library) != 0)
{
_debug("Error registering the plugin ...\n");
return 1;
}
}
}
}
}
else
return 1;
......@@ -75,89 +98,134 @@
return 0;
}
::sflphone::Plugin*
::sflphone::PluginManager::isPluginLoaded (const std::string &name)
int
PluginManager::unloadPlugins (void)
{
if(_loadedPlugins.empty()) return NULL;
PluginInfo *info;
if(_loadedPlugins.empty()) return 0;
/* Use an iterator on the loaded plugins map */
pluginMap::iterator iter;
iter = _loadedPlugins.begin();
while( iter != _loadedPlugins.end() ) {
if ( iter->first == name ) {
/* Return the associated plugin */
return iter->second;
info = iter->second;
if (deletePlugin (info) != 0)
{
_debug("Error deleting the plugin ... \n");
return 1;
}
unloadDynamicLibrary (info->_libraryPtr);
if (unregisterPlugin (info) != 0)
{
_debug("Error unregistering the plugin ... \n");
return 1;
}
iter++;
}
/* If we are here, it means that the plugin we were looking for has not been loaded */
return NULL;
return 0;
}
void*
::sflphone::PluginManager::loadDynamicLibrary (const std::string& filename)
bool
PluginManager::isPluginLoaded (const std::string &name)
{
if(_loadedPlugins.empty()) return false;
/* Use an iterator on the loaded plugins map */
pluginMap::iterator iter;
iter = _loadedPlugins.find (name);
void *pluginHandlePtr = NULL;
const char *error;
/* Returns map::end if the specified key has not been found */
if(iter==_loadedPlugins.end())
return false;
_debug("Loading dynamic library %s\n", filename.c_str());
/* Returns the plugin pointer */
return true;
}
/* Load the library */
pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY );
if( !pluginHandlePtr ) {
error = dlerror();
_debug("Error while opening plug-in: %s\n", error);
return NULL;
}
dlerror();
return pluginHandlePtr;
LibraryManager*
PluginManager::loadDynamicLibrary (const std::string& filename)
{
/* Load the library through the library manager */
return new LibraryManager (filename);
}
int
PluginManager::unloadDynamicLibrary (LibraryManager *libraryPtr)
{
_debug("Unloading dynamic library ...\n");
/* Close it */
return libraryPtr->unloadLibrary ();
}
int
::sflphone::PluginManager::instanciatePlugin (void *handlePtr, ::sflphone::PluginInterface **plugin)
PluginManager::instanciatePlugin (LibraryManager *libraryPtr, Plugin **plugin)
{
createFunc *createPlugin;
LibraryManager::SymbolHandle symbol;
createPlugin = (createFunc*)dlsym(handlePtr, "create");
if( dlerror() )
{
_debug("Error creating the plugin: %s\n", dlerror());
if (libraryPtr->resolveSymbol ("createPlugin", &symbol) != 0)
return 1;
}
createPlugin = (createFunc*)symbol;
*plugin = createPlugin();
return 0;
}
int
::sflphone::PluginManager::registerPlugin (void *handlePtr, PluginInterface *interface)
PluginManager::deletePlugin (PluginInfo *plugin)
{
Plugin *myplugin;
std::string name;
destroyFunc *destroyPlugin;
LibraryManager::SymbolHandle symbol;
if( !( handlePtr && interface!=0 ) )
if (plugin->_libraryPtr->resolveSymbol ("destroyPlugin", &symbol) != 0)
return 1;
/* Fetch information from the loaded plugin interface */
if(interface->registerFunc (&myplugin) != 0)
destroyPlugin = (destroyFunc*)symbol;
/* Call it */
destroyPlugin (plugin->_plugin);
return 0;
}
int
PluginManager::registerPlugin (Plugin *plugin, LibraryManager *library)
{
std::string key;
PluginInfo *p_info;
if( plugin==0 )
return 1;
/* Creation of the plugin wrapper */
myplugin = new Plugin (handlePtr, interface);
p_info = new PluginInfo();
/* Retrieve information from the plugin */
plugin->initFunc (&p_info);
key = p_info->_name;
//p_info->_plugin = plugin;
p_info->_libraryPtr = library;
/* Add the data in the loaded plugin map */
_loadedPlugins[ myplugin->_name ] = myplugin;
_loadedPlugins[ key ] = p_info;
return 0;
}
void
::sflphone::PluginManager::unloadDynamicLibrary (void * pluginHandlePtr)
int
PluginManager::unregisterPlugin (PluginInfo *plugin)
{
dlclose( pluginHandlePtr );
dlerror();
}
pluginMap::iterator iter;
std::string key;
key = plugin->_name;
if (!isPluginLoaded(key))
return 1;
iter = _loadedPlugins.find (key);
_loadedPlugins.erase (iter);
return 0;
}
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PLUGIN_MANAGER_H
#define PLUGIN_MANAGER_H
......@@ -6,18 +25,27 @@
* @brief Base class of the plugin manager
*/
#include "plugininterface.h"
#include "librarymanager.h"
#include "global.h"
#include <map>
#include <string>
#include <vector>
namespace sflphone {
class Plugin;
class PluginManager {
typedef struct PluginInfo {
std::string _name;
LibraryManager *_libraryPtr;
Plugin *_plugin;
int _major_version;
int _minor_version;
} PluginInfo;
#include "plugin.h"
public:
class PluginManager {
public:
/**
* Destructor
*/
......@@ -33,45 +61,51 @@ namespace sflphone {
* @param path The absolute path to the directory
* @return int The number of items loaded
*/
int loadPlugins( const std::string &path = "" );
int loadPlugins (const std::string &path = "");
int unloadPlugins (void);
int instanciatePlugin( void *handlePtr, PluginInterface** plugin );
int instanciatePlugin (LibraryManager* libraryPtr, Plugin** plugin);
/**
* Check if a plugin has been already loaded
* @param name The name of the plugin looked for
* @return Plugin* The pointer on the plugin or NULL if not found
* @return bool The pointer on the plugin or NULL if not found
*/
Plugin* isPluginLoaded( const std::string &name );
bool isPluginLoaded (const std::string &name);
int registerPlugin (void *handle, PluginInterface *interface);
int registerPlugin (Plugin *plugin, LibraryManager *library);
int unregisterPlugin (PluginInfo *plugin);
private:
/**
* Default constructor
*/