Commit 71e71378 authored by Emmanuel Milou's avatar Emmanuel Milou

Functional plug-in manager

parent f6d2fbf1
......@@ -5,6 +5,5 @@ noinst_LTLIBRARIES = libplugin.la
SUBDIRS=test
libplugin_la_SOURCES = \
pluginmanager.cpp \
plugin.cpp
pluginmanager.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"
#include <string>
#include "global.h"
namespace sflphone {
/*
* @file plugin.h
* @brief Define a plugin object
*/
class PluginInterface;
namespace sflphone {
class Plugin {
public:
Plugin( const std::string &name ){
_name = name;
}
Plugin (void*, PluginInterface *interface);
Plugin (PluginInterface *interface);
virtual ~Plugin() {}
~Plugin ();
inline std::string getPluginName (void) { return _name; }
void setName (std::string name);
/**
* Return the minimal core version required so that the plugin could work
* @return int The version required
*/
virtual int initFunc (int i) = 0;
private:
Plugin &operator =(const Plugin &plugin);
std::string _name;
int _version_major;
int _version_minor;
int _required;
void *_handlePtr;
PluginInterface *_interface;
friend class PluginTest;
friend class PluginManager;
};
}
typedef ::sflphone::Plugin* createFunc (void);
typedef void destroyFunc (::sflphone::Plugin*);
#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
......@@ -29,7 +29,7 @@
::sflphone::PluginManager::loadPlugins (const std::string &path)
{
std::string pluginDir, current;
::sflphone::PluginInterface *interface;
::sflphone::Plugin *plugin;
DIR *dir;
dirent *dirStruct;
int result=0;
......@@ -54,15 +54,18 @@
if( current != pDir && current != cDir ){
handle = loadDynamicLibrary( pluginDir + current );
if(instanciatePlugin (handle, &interface) != 0)
if(instanciatePlugin (handle, &plugin) != 0)
{
_debug("Error instanciating the plugin ...\n");
return 1;
}
/*
if(registerPlugin (handle, interface) != 0)
{
_debug("Error registering the plugin ...\n");
return 1;
}*/
}
}
}
......@@ -119,7 +122,7 @@
}
int
::sflphone::PluginManager::instanciatePlugin (void *handlePtr, ::sflphone::PluginInterface **plugin)
::sflphone::PluginManager::instanciatePlugin (void *handlePtr, ::sflphone::Plugin **plugin)
{
createFunc *createPlugin;
......@@ -134,30 +137,25 @@
}
int
::sflphone::PluginManager::registerPlugin (void *handlePtr, PluginInterface *interface)
::sflphone::PluginManager::registerPlugin (void *handlePtr, Plugin *plugin)
{
Plugin *myplugin;
std::string name;
if( !( handlePtr && interface!=0 ) )
if( !(handlePtr && plugin!=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);
name = plugin->getPluginName();
/* Add the data in the loaded plugin map */
_loadedPlugins[ myplugin->_name ] = myplugin;
_loadedPlugins[ name ] = plugin;
return 0;
}
void
int
::sflphone::PluginManager::unloadDynamicLibrary (void * pluginHandlePtr)
{
dlclose( pluginHandlePtr );
dlerror();
return 0;
}
......@@ -6,7 +6,7 @@
* @brief Base class of the plugin manager
*/
#include "plugininterface.h"
#include "plugin.h"
#include "global.h"
#include <map>
......@@ -18,6 +18,7 @@ namespace sflphone {
public:
/**
* Destructor
*/
......@@ -35,7 +36,7 @@ namespace sflphone {
*/
int loadPlugins( const std::string &path = "" );
int instanciatePlugin( void *handlePtr, PluginInterface** plugin );
int instanciatePlugin( void *handlePtr, Plugin** plugin );
/**
* Check if a plugin has been already loaded
......@@ -44,27 +45,28 @@ namespace sflphone {
*/
Plugin* isPluginLoaded( const std::string &name );
int registerPlugin (void *handle, PluginInterface *interface);
private:
/**
* Default constructor
*/
PluginManager();
int registerPlugin (void *handle, Plugin *plugin);
/**
* 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 );
int unloadDynamicLibrary( void * pluginHandlePtr );
private:
/**
* Default constructor
*/
PluginManager();
/* Map of plugins associated by their string name */
typedef std::map<std::string, Plugin*> pluginMap;
pluginMap _loadedPlugins;
......
#include "../plugininterface.h"
#include "../plugin.h"
namespace sflphone {
class PluginTest : public PluginInterface {
class PluginTest : public Plugin {
public:
PluginTest( const std::string &name ):PluginInterface( name ){
}
PluginTest( const std::string &name )
:Plugin( name ) {
}
virtual int initFunc (void)
virtual int initFunc (int i)
{
return 0;
return i;
}
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::PluginInterface* create (void){
return new ::sflphone::PluginTest("test");
extern "C" ::sflphone::Plugin* create (void){
return new ::sflphone::PluginTest("mytest");
}
extern "C" void* destroy( ::sflphone::PluginInterface *p ){
extern "C" void destroy (::sflphone::Plugin *p){
delete p;
}
......@@ -19,33 +19,67 @@
#include <stdio.h>
#include <sstream>
#include <dlfcn.h>
#include "pluginmanagerTest.h"
using std::cout;
using std::endl;
#define PLUGIN_TEST_DIR "/usr/lib/sflphone/plugins/libplugintest.so"
#define PLUGIN_TEST_NAME "mytest"
void PluginManagerTest::setUp(){
// Instanciate the plugin manager singleton
_pm = ::sflphone::PluginManager::instance();
handlePtr = NULL;
plugin = 0;
}
void PluginManagerTest::testLoadPluginDirectory(){
CPPUNIT_ASSERT(_pm->loadPlugins() == 0);
void PluginManagerTest::testLoadDynamicLibrary(){
CPPUNIT_ASSERT(_pm->loadDynamicLibrary(PLUGIN_TEST_DIR) != NULL);
}
void PluginManagerTest::testUnloadDynamicLibrary(){
handlePtr = _pm->loadDynamicLibrary(PLUGIN_TEST_DIR);
CPPUNIT_ASSERT(handlePtr != 0);
CPPUNIT_ASSERT(_pm->unloadDynamicLibrary(handlePtr) == 0 );
}
void PluginManagerTest::testLoadPlugin(){
CPPUNIT_ASSERT(_pm->loadPlugins() == 0);
//CPPUNIT_ASSERT( _pm->isPluginLoaded("test") == NULL );
void PluginManagerTest::testInstanciatePlugin(){
handlePtr = _pm->loadDynamicLibrary (PLUGIN_TEST_DIR);
CPPUNIT_ASSERT (handlePtr != 0);
CPPUNIT_ASSERT (_pm->instanciatePlugin (handlePtr, &plugin) == 0);
CPPUNIT_ASSERT (plugin!=NULL);
}
void PluginManagerTest::testInitPlugin(){
handlePtr = _pm->loadDynamicLibrary (PLUGIN_TEST_DIR);
CPPUNIT_ASSERT (handlePtr != 0);
CPPUNIT_ASSERT (_pm->instanciatePlugin (handlePtr, &plugin) == 0);
CPPUNIT_ASSERT (plugin!=NULL);
CPPUNIT_ASSERT (plugin->initFunc(0) == 0);
CPPUNIT_ASSERT (plugin->getPluginName() == PLUGIN_TEST_NAME);
}
void PluginManagerTest::testRegisterPlugin(){
// First load the default directory
_pm->loadPlugins();
// Resolve the symbol
handlePtr = _pm->loadDynamicLibrary (PLUGIN_TEST_DIR);
CPPUNIT_ASSERT (handlePtr != 0);
CPPUNIT_ASSERT (_pm->instanciatePlugin (handlePtr, &plugin) == 0);
CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_NAME) == NULL);
CPPUNIT_ASSERT (_pm->registerPlugin (handlePtr, plugin) == 0);
CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_NAME) == plugin);
}
void PluginManagerTest::tearDown(){
// Delete the plugin manager object
delete _pm; _pm=0;
handlePtr = NULL;
if(plugin)
delete plugin; plugin = 0;
}
......@@ -27,6 +27,7 @@
// Application import
#include "plug-in/pluginmanager.h"
#include "plug-in/plugin.h"
/*
* @file pluginManagerTest.cpp
......@@ -38,12 +39,16 @@
class PluginManagerTest : public CppUnit::TestCase {
class Plugin;
/*
* Use cppunit library macros to add unit test the factory
*/
CPPUNIT_TEST_SUITE( PluginManagerTest );
CPPUNIT_TEST( testLoadPluginDirectory );
CPPUNIT_TEST( testLoadPlugin );
CPPUNIT_TEST( testLoadDynamicLibrary );
CPPUNIT_TEST( testUnloadDynamicLibrary );
CPPUNIT_TEST( testInstanciatePlugin );
CPPUNIT_TEST( testInitPlugin );
CPPUNIT_TEST( testRegisterPlugin );
CPPUNIT_TEST_SUITE_END();
......@@ -62,14 +67,20 @@ class PluginManagerTest : public CppUnit::TestCase {
*/
inline void tearDown();
void testLoadPluginDirectory();
void testLoadDynamicLibrary();
void testLoadPlugin();
void testUnloadDynamicLibrary();
void testInstanciatePlugin();
void testInitPlugin();
void testRegisterPlugin();
private:
::sflphone::PluginManager *_pm;
void *handlePtr;
::sflphone::Plugin *plugin;
};
/* Register our test module */
......
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