new plugin code, based on QPlugin

svn path=/trunk/kdesupport/qca/; revision=393688
This commit is contained in:
Justin Karneges 2005-02-28 02:28:23 +00:00
parent 7dc68f5e61
commit 0e1c7408e8
6 changed files with 68 additions and 74 deletions

3
TODO
View File

@ -1,6 +1,7 @@
* Additional unit tests * Additional unit tests
* Bundle root certificates to be used on platforms without a system store * Bundle root certificates to be used on platforms without a system store
(we need to choose a reliable source, maybe mozilla or debian? kde??) (we need to choose a reliable source, maybe mozilla or debian? kde??)
* Update to latest Botan, and remake the botantools patch as appropriate
* API documentation * API documentation
clean up Algorithm clean up Algorithm
@ -16,13 +17,11 @@
threading (safety, usability) in API and plugins. look for singletons threading (safety, usability) in API and plugins. look for singletons
it's possible we use QSecureArray in some unnecessary places it's possible we use QSecureArray in some unnecessary places
don't forget to QCA_EXPORT everything don't forget to QCA_EXPORT everything
ensure plugin system is upgradable this time. no createProvider3(), please..
standardize on count() vs size() when iterating? standardize on count() vs size() when iterating?
* finish API: * finish API:
do something about qhostaddress in SASL. try to remove QtNetwork dependency? do something about qhostaddress in SASL. try to remove QtNetwork dependency?
move to qt 4 move to qt 4
use qplugin
use qshareddata for thread-safe objects use qshareddata for thread-safe objects
turn ambiguous bool args into enums turn ambiguous bool args into enums
create include files for all class names? create include files for all class names?

View File

@ -287,6 +287,12 @@ namespace QCA
*/ */
QCA_EXPORT const ProviderList & providers(); QCA_EXPORT const ProviderList & providers();
/**
* Scan for new plugins
*
*/
QCA_EXPORT void scanForPlugins();
/** /**
* Unload the current plugins * Unload the current plugins
* *

View File

@ -31,10 +31,6 @@
#define QCA_PLUGIN_VERSION 2 #define QCA_PLUGIN_VERSION 2
#define QCA_EXPORT_PLUGIN(P) \
QCA_PLUGIN_EXPORT QCA::Provider *createProvider2() { return new P; } \
QCA_PLUGIN_EXPORT int version() { return QCA_PLUGIN_VERSION; }
/** \page providers Providers /** \page providers Providers
QCA works on the concept of a "provider". There is a limited QCA works on the concept of a "provider". There is a limited
@ -53,6 +49,14 @@ whatsoever, or to specify the default provider directly (this goes for the
algorithm constructors as well as setGlobalRNG()). algorithm constructors as well as setGlobalRNG()).
*/ */
class QCAPlugin : public QObject
{
Q_OBJECT
public:
virtual int version() const = 0;
virtual QCA::Provider *createProvider() = 0;
};
namespace QCA { namespace QCA {
class RandomContext : public Provider::Context class RandomContext : public Provider::Context

View File

@ -179,6 +179,11 @@ const ProviderList & providers()
return manager->providers(); return manager->providers();
} }
void scanForPlugins()
{
manager->scan();
}
void unloadAllPlugins() void unloadAllPlugins()
{ {
if(!qca_init) if(!qca_init)

View File

@ -23,14 +23,6 @@
#include <QtCore> #include <QtCore>
#include "qcaprovider.h" #include "qcaprovider.h"
#if defined(Q_OS_WIN32)
# define PLUGIN_EXT "dll"
#elif defined(Q_OS_MAC)
# define PLUGIN_EXT "dylib"
#else
# define PLUGIN_EXT "so"
#endif
#define PLUGIN_SUBDIR "crypto" #define PLUGIN_SUBDIR "crypto"
namespace QCA { namespace QCA {
@ -38,73 +30,43 @@ namespace QCA {
class ProviderItem class ProviderItem
{ {
public: public:
QCA::Provider *p; Provider *p;
QString fname; QString fname;
int version;
int priority; int priority;
static ProviderItem *load(const QString &fname) static ProviderItem *load(const QString &fname)
{ {
QLibrary *lib = new QLibrary(fname); QPluginLoader *lib = new QPluginLoader(fname);
if(!lib->load()) QCAPlugin *plugin = qobject_cast<QCAPlugin*>(lib->instance());
if(!plugin || plugin->version() != QCA_PLUGIN_VERSION)
{ {
delete lib; delete lib;
return 0; return 0;
} }
int ver = 0; Provider *p = plugin->createProvider();
bool old; if(!p)
void *s = lib->resolve("version");
if(s)
{
old = false;
int (*versionfunc)() = (int (*)())s;
ver = versionfunc();
}
else
{
old = true;
}
if(old)
s = lib->resolve("createProvider");
else
s = lib->resolve("createProvider2");
if(!s)
{ {
delete lib; delete lib;
return 0; return 0;
} }
ProviderItem *i; ProviderItem *i = new ProviderItem(lib, p);
if(old)
{
// old method
//QCAProvider *(*createProvider)() = (QCAProvider *(*)())s;
//QCAProvider *p = createProvider();
//if(!p)
//{
delete lib;
return 0;
//}
//ver = p->qcaVersion();
//i = new ProviderItem(lib, p);
}
else
{
// new method
QCA::Provider *(*createProvider)() = (QCA::Provider *(*)())s;
QCA::Provider *p = createProvider();
if(!p)
{
delete lib;
return 0;
}
i = new ProviderItem(lib, p);
}
i->fname = fname; i->fname = fname;
i->version = ver; return i;
}
static ProviderItem *loadStatic(QObject *instance)
{
QCAPlugin *plugin = qobject_cast<QCAPlugin*>(instance);
if(!plugin || plugin->version() != QCA_PLUGIN_VERSION)
return 0;
Provider *p = plugin->createProvider();
if(!p)
return 0;
ProviderItem *i = new ProviderItem(0, p);
return i; return i;
} }
@ -129,10 +91,10 @@ public:
} }
private: private:
QLibrary *lib; QPluginLoader *lib;
bool init_done; bool init_done;
ProviderItem(QLibrary *_lib, QCA::Provider *_p) ProviderItem(QPluginLoader *_lib, QCA::Provider *_p)
{ {
lib = _lib; lib = _lib;
p = _p; p = _p;
@ -143,6 +105,7 @@ private:
ProviderManager::ProviderManager() ProviderManager::ProviderManager()
{ {
def = 0; def = 0;
scanned_static = false;
} }
ProviderManager::~ProviderManager() ProviderManager::~ProviderManager()
@ -152,6 +115,29 @@ ProviderManager::~ProviderManager()
void ProviderManager::scan() void ProviderManager::scan()
{ {
// check static first, but only once
if(!scanned_static)
{
QObjectList list = QPluginLoader::staticInstances();
for(int n = 0; n < list.count(); ++n)
{
QObject *instance = list[n];
ProviderItem *i = ProviderItem::loadStatic(instance);
if(!i)
continue;
if(i->p && haveAlready(i->p->name()))
{
delete i;
continue;
}
addItem(i, -1);
}
scanned_static = true;
}
// check plugin files
QStringList dirs = QCoreApplication::libraryPaths(); QStringList dirs = QCoreApplication::libraryPaths();
for(QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) for(QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it)
{ {
@ -166,18 +152,11 @@ void ProviderManager::scan()
QFileInfo fi(dir.filePath(*it)); QFileInfo fi(dir.filePath(*it));
if(fi.isDir()) if(fi.isDir())
continue; continue;
if(fi.suffix() != PLUGIN_EXT)
continue;
QString fname = fi.filePath(); QString fname = fi.filePath();
ProviderItem *i = ProviderItem::load(fname); ProviderItem *i = ProviderItem::load(fname);
if(!i) if(!i)
continue; continue;
if(i->version != QCA_PLUGIN_VERSION)
{
delete i;
continue;
}
if(i->p && haveAlready(i->p->name())) if(i->p && haveAlready(i->p->name()))
{ {

View File

@ -54,6 +54,7 @@ namespace QCA
QList<ProviderItem*> providerItemList; QList<ProviderItem*> providerItemList;
QCA::ProviderList providerList; QCA::ProviderList providerList;
QCA::Provider *def; QCA::Provider *def;
bool scanned_static;
void addItem(ProviderItem *i, int priority); void addItem(ProviderItem *i, int priority);
bool haveAlready(const QString &name) const; bool haveAlready(const QString &name) const;
}; };