/*************************************************************************** begin : Mon Jan 13 2003 copyright : (C) 2003 by Andrew Sutton email : ansutton@kent.edu ***************************************************************************/ /*************************************************************************** * * * 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // own header #include "pluginloader.h" // TQt includes #include // KDE includes #include #include // u2 includes #include "plugin.h" using namespace Umbrello; // static data PluginLoader *PluginLoader::_instance = NULL; PluginLoader::PluginLoader() : _plugins(), _categories() { // preseed the categories _categories["metamodel"] = PluginList(); _categories["storage"] = PluginList(); _categories["visual"] = PluginList(); } PluginLoader::~PluginLoader() { } PluginLoader * PluginLoader::instance() { if(!_instance) _instance = new PluginLoader; return _instance; } Plugin * PluginLoader::loadPlugin(const TQString &name) { KLibrary *lib = NULL; KLibFactory *factory = NULL; Plugin *plugin = NULL; PluginMap::iterator it; bool success = true; // if the plugin has already been loaded, increment // its reference and return. if((it = _plugins.find(name)) != _plugins.end()) { plugin = it.data(); plugin->ref(); return plugin; } // use KLibLoader to get a reference to the library lib = KLibLoader::self()->library(name.latin1()); if(!lib) { kdError() << "failed loading plugin library " << name << endl; success = false; } // get the factory from the library if(success) { factory = lib->factory(); if(!factory) { kdError() << "failed to find factory for " << name << endl; success = false; } } // use the factory to create the plugin if(success) { plugin = dynamic_cast(factory->create((TQObject*)0, name.latin1())); if(!plugin) { kdError() << "failed to create a plugin object for " << name << endl; success = false; } else { // we have to register the plugin here, otherwise, we can get // recursive loads _plugins[name] = plugin; _categories[plugin->category()].append(plugin); } } // initialize the plugin if(success && plugin) { success = plugin->init(); if(!success) { // on failure, delete the plugin. this should cause the // library to unload. kdError() << "failure initializing " << name << endl; _categories[plugin->category()].remove(plugin); _plugins.remove(name); delete plugin; } } // finally, finally connect to the destroyed signal and keep a // reference to it if(success) { plugin->ref(); connect(plugin, TQT_SIGNAL(destroyed(TQObject *)), TQT_SLOT(slotDestroyed(TQObject *))); } return plugin; } Plugin * PluginLoader::findPlugin(const TQString &name) { Plugin *ret = NULL; PluginMap::iterator it = _plugins.find(name); if(it != _plugins.end()) { ret = it.data(); } return ret; } void PluginLoader::unloadPlugin(const TQString &name) { KLibLoader::self()->unloadLibrary(name.latin1()); } const PluginLoader::PluginMap & PluginLoader::plugins() const { return _plugins; } const PluginLoader::CategoryMap & PluginLoader::categories() const { return _categories; } void PluginLoader::slotDestroyed(TQObject *obj) { Plugin *plugin = static_cast(obj); // we can't just use the name because its already been destroyed // at this point. we have to iterate thru and find the reference // by hand. PluginMap::iterator end(_plugins.end()); for(PluginMap::iterator i = _plugins.begin(); i != end; ++i) { Plugin *p = i.data(); if(p == plugin) { kdDebug() << "unloading plugin " << i.key() << endl; // remove it from the mapping _plugins.remove(i); break; } } } #include "pluginloader.moc"