Commit f6d2fbf1 authored by Emmanuel Milou's avatar Emmanuel Milou

Make the plugins registering against the plugin manager

parent 4f509b09
......@@ -5,5 +5,6 @@ noinst_LTLIBRARIES = libplugin.la
SUBDIRS=test
libplugin_la_SOURCES = \
pluginmanager.cpp
pluginmanager.cpp \
plugin.cpp
#include "plugin.h"
::sflphone::Plugin::Plugin (void *handle, PluginInterface *interface)
:_handlePtr(handle), _interface(interface)
{
}
::sflphone::Plugin::Plugin (PluginInterface *interface)
:_interface(interface)
{
}
::sflphone::Plugin::~Plugin ()
{
}
#ifndef PLUGIN_H
#define PLUGIN_H
#include "plugininterface.h"
namespace sflphone {
class PluginInterface;
class Plugin {
public:
Plugin (void*, PluginInterface *interface);
Plugin (PluginInterface *interface);
~Plugin ();
void setName (std::string name);
private:
std::string _name;
int _version_major;
int _version_minor;
int _required;
void *_handlePtr;
PluginInterface *_interface;
friend class PluginTest;
friend class PluginManager;
};
}
#endif //PLUGIN_H
#ifndef PLUGIN_H
#define PLUGIN_H
#include <string>
#include "global.h"
/*
* @file plugin.h
* @brief Define a plugin object
*/
#ifdef __cplusplus
extern "C" {
#endif
namespace sflphone {
class PluginManager;
class Plugin {
public:
Plugin( const std::string &name ){
_name = name;
}
virtual ~Plugin() {}
public:
/**
* Return the minimal core version required so that the plugin could work
* @return int The version required
*/
virtual int getCoreVersion() const = 0;
private:
Plugin &operator =(const Plugin &plugin);
std::string _name;
};
typedef Plugin* createFunc( void* );
typedef void destroyFunc( Plugin* );
}
#ifdef __cplusplus
}
#endif
#endif //PLUGIN_H
#ifndef PLUGIN_INTERFACE_H
#define PLUGIN_INTERFACE_H
#include <string>
#include "global.h"
#include "plugin.h"
/*
* @file plugininterface.h
* @brief Define a plugin object
*/
namespace sflphone {
class PluginManager;
class Plugin;
class PluginInterface {
public:
PluginInterface( const std::string &name ){
_name = name;
}
virtual ~PluginInterface() {}
inline std::string getInterfaceName (void) { return _name; }
/**
* Return the minimal core version required so that the plugin could work
* @return int The version required
*/
virtual int initFunc () = 0;
virtual int registerFunc (Plugin **plugin) = 0;
private:
PluginInterface &operator =(const PluginInterface &plugin);
std::string _name;
};
typedef PluginInterface* createFunc (void);
typedef void destroyFunc( PluginInterface* );
}
#endif //PLUGIN_INTERFACE_H
......@@ -3,7 +3,19 @@
#include "pluginmanager.h"
::sflphone::PluginManager::PluginManager():_loadedPlugins()
::sflphone::PluginManager* ::sflphone::PluginManager::_instance = 0;
::sflphone::PluginManager*
::sflphone::PluginManager::instance()
{
if(!_instance){
return new PluginManager();
}
return _instance;
}
::sflphone::PluginManager::PluginManager()
:_loadedPlugins()
{
_instance = this;
}
......@@ -13,13 +25,16 @@
_instance = 0;
}
int ::sflphone::PluginManager::loadPlugins( const std::string &path )
int
::sflphone::PluginManager::loadPlugins (const std::string &path)
{
std::string pluginDir, current;
::sflphone::Plugin *plugin;
::sflphone::PluginInterface *interface;
DIR *dir;
dirent *dirStruct;
int result=0;
void *handle;
createFunc* createPlugin;
const std::string pDir = "..";
const std::string cDir = ".";
......@@ -37,18 +52,31 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path )
current = dirStruct->d_name;
/* Test if the current item is not the parent or the current directory */
if( current != pDir && current != cDir ){
loadDynamicLibrary( current );
result++;
}
handle = loadDynamicLibrary( pluginDir + current );
if(instanciatePlugin (handle, &interface) != 0)
{
_debug("Error instanciating the plugin ...\n");
return 1;
}
if(registerPlugin (handle, interface) != 0)
_debug("Error registering the plugin ...\n");
return 1;
}
}
}
else
return 1;
/* Close the directory */
closedir( dir );
return result;
return 0;
}
::sflphone::PluginWrap* ::sflphone::PluginManager::isPluginLoaded( const std::string &name )
::sflphone::Plugin*
::sflphone::PluginManager::isPluginLoaded (const std::string &name)
{
if(_loadedPlugins.empty()) return NULL;
......@@ -68,31 +96,68 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path )
return NULL;
}
void* ::sflphone::PluginManager::loadDynamicLibrary( const std::string& filename ) {
void*
::sflphone::PluginManager::loadDynamicLibrary (const std::string& filename)
{
void *pluginHandlePtr = NULL;
const char *error;
_debug("Loading dynamic library %s\n", filename.c_str());
#if defined(Q_OS_UNIX)
/* 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();
#endif
return pluginHandlePtr;
}
void ::sflphone::PluginManager::unloadDynamicLibrary( void * pluginHandlePtr ) {
int
::sflphone::PluginManager::instanciatePlugin (void *handlePtr, ::sflphone::PluginInterface **plugin)
{
createFunc *createPlugin;
createPlugin = (createFunc*)dlsym(handlePtr, "create");
if( dlerror() )
{
_debug("Error creating the plugin: %s\n", dlerror());
return 1;
}
*plugin = createPlugin();
return 0;
}
int
::sflphone::PluginManager::registerPlugin (void *handlePtr, PluginInterface *interface)
{
Plugin *myplugin;
std::string name;
if( !( handlePtr && interface!=0 ) )
return 1;
/* Fetch information from the loaded plugin interface */
if(interface->registerFunc (&myplugin) != 0)
return 1;
/* Creation of the plugin wrapper */
myplugin = new Plugin (handlePtr, interface);
/* Add the data in the loaded plugin map */
_loadedPlugins[ myplugin->_name ] = myplugin;
return 0;
}
void
::sflphone::PluginManager::unloadDynamicLibrary (void * pluginHandlePtr)
{
dlclose( pluginHandlePtr );
dlerror();
}
::sflphone::PluginManager* ::sflphone::PluginManager::_instance = 0;
......@@ -6,77 +6,71 @@
* @brief Base class of the plugin manager
*/
#include "plugin_api.h"
#include "plugininterface.h"
#include "global.h"
#include <map>
#include <string>
namespace sflphone {
typedef struct {
Plugin *plugin;
createFunc *create_func;
destroyFunc *destroy_func;
std::string name;
} PluginWrap;
class PluginManager {
public:
/**
* Default constructor
*/
PluginManager();
/**
* Destructor
*/
~PluginManager();
/**
* Returns the unique instance of the plugin manager
*/
static PluginManager* instance();
/**
* Load all the plugins found in a specific directory
* @param path The absolute path to the directory
* @return int The number of items loaded
*/
int loadPlugins( const std::string &path = "" );
/**
* 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
*/
PluginWrap* isPluginLoaded( const std::string &name );
int initPlugins( void );
/**
* Destructor
*/
~PluginManager();
/**
* Returns the unique instance of the plugin manager
*/
static PluginManager* instance();
/**
* Load all the plugins found in a specific directory
* @param path The absolute path to the directory
* @return int The number of items loaded
*/
int loadPlugins( const std::string &path = "" );
int instanciatePlugin( void *handlePtr, PluginInterface** 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
*/
Plugin* isPluginLoaded( const std::string &name );
int registerPlugin (void *handle, PluginInterface *interface);
private:
/**
* Load a unix dynamic/shared library
* @param filename The path to the dynamic/shared library
* @return void* A pointer on it
*/
void * loadDynamicLibrary( const std::string &filename );
/**
* Unload a unix dynamic/shared library
* @param pluginHandleptr The pointer on the loaded plugin
*/
void unloadDynamicLibrary( void * pluginHandlePtr );
/* Map of plugins associated by their string name */
typedef std::map<std::string, ::sflphone::PluginWrap*> pluginMap;
pluginMap _loadedPlugins;
/* The unique static instance */
static PluginManager* _instance;
/**
* Default constructor
*/
PluginManager();
/**
* Load a unix dynamic/shared library
* @param filename The path to the dynamic/shared library
* @return void* A pointer on it
*/
void * loadDynamicLibrary( const std::string &filename );
/**
* Unload a unix dynamic/shared library
* @param pluginHandleptr The pointer on the loaded plugin
*/
void unloadDynamicLibrary( void * pluginHandlePtr );
/* Map of plugins associated by their string name */
typedef std::map<std::string, Plugin*> pluginMap;
pluginMap _loadedPlugins;
/* The unique static instance */
static PluginManager* _instance;
};
}
......
#include "../plugin_api.h"
#include "../plugininterface.h"
namespace sflphone {
class PluginTest : public Plugin {
class PluginTest : public PluginInterface {
public:
PluginTest( const std::string &name ):Plugin( name ){
PluginTest( const std::string &name ):PluginInterface( name ){
}
virtual int getCoreVersion() const{
return 1;
virtual int initFunc (void)
{
return 0;
}
virtual int registerFunc (Plugin **plugin)
{
Plugin *ret;
ret = new Plugin(this);
ret->_name = getInterfaceName();
ret->_required = 1;
ret->_version_major=1;
ret->_version_minor=0;
*plugin = ret;
return 0;
}
};
}
extern "C" ::sflphone::Plugin* create_t( void * ){
extern "C" ::sflphone::PluginInterface* create (void){
return new ::sflphone::PluginTest("test");
}
extern "C" void* destroy_t( ::sflphone::Plugin *p ){
extern "C" void* destroy( ::sflphone::PluginInterface *p ){
delete p;
}
......@@ -15,7 +15,6 @@ OBJECT_FILES= \
../src/sflphoned-sipaccount.o \
../src/sflphoned-iaxaccount.o \
../src/sflphoned-eventthread.o \
../src/sflphoned-useragent.o \
../src/plug-in/pluginmanager.o \
../src/sflphoned-samplerateconverter.o
......
......@@ -26,19 +26,26 @@ using std::cout;
using std::endl;
void PluginManagerTest::setUp(){
// Instanciate the plugin manager object
_pm = new ::sflphone::PluginManager();
// Instanciate the plugin manager singleton
_pm = ::sflphone::PluginManager::instance();
}
void PluginManagerTest::testLoadPluginDirectory(){
_pm->loadPlugins();
CPPUNIT_ASSERT(_pm->loadPlugins() == 0);
}
void PluginManagerTest::testLoadPlugin(){
CPPUNIT_ASSERT(_pm->loadPlugins() == 0);
//CPPUNIT_ASSERT( _pm->isPluginLoaded("test") == NULL );
}
void PluginManagerTest::testNonloadedPlugin(){
CPPUNIT_ASSERT( _pm->isPluginLoaded("test") == NULL );
void PluginManagerTest::testRegisterPlugin(){
// First load the default directory
_pm->loadPlugins();
// Resolve the symbol
}
void PluginManagerTest::tearDown(){
// Delete the plugin manager object
delete _pm; _pm=NULL;
delete _pm; _pm=0;
}
......@@ -43,7 +43,8 @@ class PluginManagerTest : public CppUnit::TestCase {
*/
CPPUNIT_TEST_SUITE( PluginManagerTest );
CPPUNIT_TEST( testLoadPluginDirectory );
CPPUNIT_TEST( testNonloadedPlugin );
CPPUNIT_TEST( testLoadPlugin );
CPPUNIT_TEST( testRegisterPlugin );
CPPUNIT_TEST_SUITE_END();
public:
......@@ -63,7 +64,9 @@ class PluginManagerTest : public CppUnit::TestCase {
void testLoadPluginDirectory();
void testNonloadedPlugin();
void testLoadPlugin();
void testRegisterPlugin();
private:
::sflphone::PluginManager *_pm;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment