? pluggable-loaders-1.diff ? unix/tmp Index: unix/xap_UnixModule.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/unix/xap_UnixModule.h,v retrieving revision 1.6 diff -a -u -r1.6 xap_UnixModule.h --- unix/xap_UnixModule.h 12 Sep 2001 17:51:44 -0000 1.6 +++ unix/xap_UnixModule.h 4 Feb 2005 09:40:56 -0000 @@ -27,19 +27,14 @@ // The Unix/GLib impl. of XAP_Module interface class XAP_UnixModule : public XAP_Module -{ - friend class XAP_ModuleManager; - -protected: +{ +public: XAP_UnixModule () ; virtual ~XAP_UnixModule (void); - + virtual bool load (const char * name); virtual bool unload (void); - -public: - virtual bool resolveSymbol (const char * symbol_name, void ** symbol); virtual bool getModuleName (char ** dest) const; virtual bool getErrorMsg (char ** dest) const; Index: xp/GNUmakefile.am =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/GNUmakefile.am,v retrieving revision 1.30 diff -a -u -r1.30 GNUmakefile.am --- xp/GNUmakefile.am 10 Feb 2004 15:19:52 -0000 1.30 +++ xp/GNUmakefile.am 4 Feb 2005 09:40:57 -0000 @@ -63,6 +63,7 @@ xap_Spider.cpp \ xap_Module.cpp \ xap_ModuleManager.cpp \ + xap_DefaultModuleFactory.cpp \ xap_Prefs.cpp \ xap_Preview.cpp \ xap_Preview_Zoom.cpp \ Index: xp/xap_DefaultModuleFactory.cpp =================================================================== RCS file: xp/xap_DefaultModuleFactory.cpp diff -N xp/xap_DefaultModuleFactory.cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ xp/xap_DefaultModuleFactory.cpp 4 Feb 2005 09:40:57 -0000 @@ -0,0 +1,155 @@ +/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ + +/* AbiSource Application Framework + * Copyright (C) 2005 Robert Staudinger + * + * 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. + * + * 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., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "ut_exception.h" +#include "ut_vector.h" +#include "ut_assert.h" +#include "ut_debugmsg.h" + +#include "xap_App.h" +#include "xap_Prefs.h" +#include "xap_Module.h" +#include "xap_Spider.h" +#include "xap_DefaultModuleFactory.h" + + +// the loader manages instances of one of these target classes + +#if defined (WIN32) + #include "xap_Win32Module.h" + #define MODULE_CLASS XAP_Win32Module + +#elif defined (__BEOS__) + #include "xap_BeOSModule.h" + #define MODULE_CLASS XAP_BeOSModule + +#elif defined (__QNXNTO__) + #include "xap_QNXModule.h" + #define MODULE_CLASS XAP_QNXModule + +#elif defined (__APPLE__) && defined (XP_MAC_TARGET_MACOSX) + #if defined (XP_MAC_TARGET_CARBON) + #include + #if defined(TARGET_RT_MAC_CFM) && (TARGET_RT_MAC_CFM == 1) + #include "xap_MacCFMModule.h" + #define MODULE_CLASS XAP_MacModule + #elif defined (TARGET_RT_MAC_MACHO) && (TARGET_RT_MAC_MACHO == 1) + #include "xap_MacModule.h" + #define MODULE_CLASS XAP_MacModule + #else + #error Unknown Apple architecture + #endif + #elif defined (XP_TARGET_COCOA) + #include "xap_CocoaModule.h" + #define MODULE_CLASS XAP_CocoaModule + #endif +#else + // *NIX + #include "xap_UnixModule.h" + #define MODULE_CLASS XAP_UnixModule + +#endif + + +// log information about plugin loading into the section of AbiWord.profile +// (we save the prefs file after each call, so as to maximise the information we have in +// case a plugin crashes and the crash handler does not get a chance to save it for us +#define XAP_DEFAULT_MODULE_FACTORY_LOAD_LOG(msg1, msg2) \ +if(XAP_App::getApp() && XAP_App::getApp()->getPrefs()) \ +{ \ + UT_String __s; \ + UT_String_sprintf(__s, "(L%d): %s %s", __LINE__, msg1, msg2); \ + UT_DEBUGMSG(("%s\n",__s.c_str())); \ + XAP_App::getApp()->getPrefs()->log("XAP_DefaultModuleFactory::loadModule", __s.c_str()); \ + XAP_App::getApp()->getPrefs()->savePrefsFile(); \ +} + + +XAP_Module * +XAP_DefaultModuleFactory::loadModule (const char * szFilename) +{ + UT_ASSERT (szFilename); + + if ( szFilename == 0) return NULL; + if (*szFilename == 0) return NULL; + + XAP_DEFAULT_MODULE_FACTORY_LOAD_LOG ("loading", szFilename); + + + // load plugin + XAP_Module * pModule = NULL; + UT_TRY { + pModule = new MODULE_CLASS; + } + UT_CATCH (...) { + pModule = 0; + return NULL; + } + + if (!pModule->load (szFilename)) { + + XAP_DEFAULT_MODULE_FACTORY_LOAD_LOG ("failed to load", szFilename) + + char * errorMsg = 0; + if (pModule->getErrorMsg (&errorMsg)) { + + XAP_DEFAULT_MODULE_FACTORY_LOAD_LOG ("error msg", errorMsg) + FREEP (errorMsg); + } + delete pModule; + return NULL; + } + + /* we (somehow :^) got here. count our blessings and return + */ + return pModule; +} + +bool +XAP_DefaultModuleFactory::unloadModule (XAP_Module * pModule) +{ + // we're less picky when unloading than we are when loading + // the (necessarily true) assumptions are that + // registerThySelf() worked + // + // so it had better damn well work in the opposite direction! + + bool bUnloaded = pModule->unregisterThySelf (); + if (bUnloaded) { + + pModule->setLoaded (false); + + bUnloaded = pModule->unload (); + if (bUnloaded) { + + delete pModule; + pModule = NULL; + return TRUE; + } + } + return FALSE; +} + +XAP_Module * +XAP_DefaultModuleFactory::newModule () +{ + return new MODULE_CLASS; +} Index: xp/xap_DefaultModuleFactory.h =================================================================== RCS file: xp/xap_DefaultModuleFactory.h diff -N xp/xap_DefaultModuleFactory.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ xp/xap_DefaultModuleFactory.h 4 Feb 2005 09:40:58 -0000 @@ -0,0 +1,50 @@ +/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ + +/* AbiSource Application Framework + * Copyright (C) 2005 Robert Staudinger + * + * 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. + * + * 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., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef XAP_DEFAULT_MODULE_FACTORY_H +#define XAP_DEFAULT_MODULE_FACTORY_H + +#include "xap_ModuleFactory.h" + +class XAP_Module; +class XAP_Spider; + +/*! +* Abiword's own plugin loader. +* This loader is used if no other loaders are present or if all rejected +* loading of a certain module. +*/ +class ABI_EXPORT XAP_DefaultModuleFactory : public XAP_ModuleFactory +{ + friend class XAP_ModuleManager; + +public: + + const char * getName (void) { return "Default Factory"; } + XAP_Module * loadModule (const char * szFilename); + bool unloadModule (XAP_Module * pModule); + +protected: + + XAP_Module * newModule (); +}; + +#endif /* XAP_DEFAULT_MODULE_FACTORY_H */ Index: xp/xap_Module.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_Module.h,v retrieving revision 1.27 diff -a -u -r1.27 xap_Module.h --- xp/xap_Module.h 16 Jun 2003 17:14:11 -0000 1.27 +++ xp/xap_Module.h 4 Feb 2005 09:40:58 -0000 @@ -61,6 +61,7 @@ class XAP_Spider; class XAP_ModuleManager; +class XAP_ModuleFactory; typedef int (*XAP_Plugin_Registration) (XAP_ModuleInfo * mi); typedef int (*XAP_Plugin_VersionCheck) (UT_uint32 major, UT_uint32 minor, UT_uint32 release); @@ -68,19 +69,20 @@ class ABI_EXPORT XAP_Module { friend class XAP_ModuleManager; + friend class XAP_DefaultModuleFactory; protected: XAP_Module (); - + +public: virtual ~XAP_Module (void); - + // load this module into memory. true on success virtual bool load (const char * name) = 0; // unload this module from memory. true on success virtual bool unload (void) = 0; - -public: + // marks the module as loaded; returns false if module is already loaded bool setSymbols (XAP_Plugin_Registration fnRegister, XAP_Plugin_Registration fnDeregister, @@ -95,7 +97,7 @@ bool supportsAbiVersion (UT_uint32 major, UT_uint32 minor, UT_uint32 release); inline void setSpider (XAP_Spider * spider) { m_spider = spider; } - inline void setCreator (XAP_ModuleManager * creator) {m_creator = creator;} + inline void setCreator (XAP_ModuleFactory * creator) {m_creator = creator;} inline void setLoaded (bool bLoaded) {m_bLoaded = bLoaded;} public: @@ -116,7 +118,7 @@ // calls failing. If return is true, you must FREEP dest virtual bool getErrorMsg (char ** dest) const = 0; - inline XAP_ModuleManager * getCreator () const {return m_creator;} + inline XAP_ModuleFactory * getCreator () const {return m_creator;} inline const XAP_ModuleInfo *getModuleInfo (void) const {return &m_info;} @@ -127,7 +129,7 @@ XAP_Plugin_VersionCheck m_fnSupportsVersion; XAP_Spider * m_spider; - XAP_ModuleManager * m_creator; + XAP_ModuleFactory * m_creator; bool m_bLoaded; bool m_bRegistered; int m_iStatus; Index: xp/xap_ModuleFactory.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_ModuleFactory.h,v retrieving revision 1.1 diff -a -u -r1.1 xap_ModuleFactory.h --- xp/xap_ModuleFactory.h 2 Feb 2005 17:20:30 -0000 1.1 +++ xp/xap_ModuleFactory.h 4 Feb 2005 09:40:58 -0000 @@ -24,9 +24,13 @@ #include "xap_Module.h" +/*! +* Interface for pluggable module loaders. +* \see XAP_ModuleManager::registerFactory() +* \see XAP_ModuleManager::unregisterFactory() +*/ class ABI_EXPORT XAP_ModuleFactory { - friend class XAP_Module; public: @@ -46,7 +50,9 @@ * Plugin factories can implement this method if they want to handle unloading of * plugins themselves. * \param module Ptr to module instance. - * \return TRUE on success, FALSE on failure. + * \return TRUE on success, FALSE on failure or if the factory is not responsible for the module. + * This method can also be used for bookkeeping of an internal list of a factory's own modules. + * If FALSE is returned the actual unloading will be done by the default factory. */ virtual bool unloadModule (XAP_Module * module) { return false; } }; Index: xp/xap_ModuleManager.cpp =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_ModuleManager.cpp,v retrieving revision 1.25 diff -a -u -r1.25 xap_ModuleManager.cpp --- xp/xap_ModuleManager.cpp 13 Dec 2004 17:38:02 -0000 1.25 +++ xp/xap_ModuleManager.cpp 4 Feb 2005 09:40:59 -0000 @@ -3,6 +3,7 @@ /* AbiSource Application Framework * Copyright (C) 2001 AbiSource, Inc. * Copyright (C) 2001 Dom Lachowicz + * Copyright (C) 2005 Robert Staudinger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -27,46 +28,16 @@ #include "xap_Spider.h" #include "xap_ModuleManager.h" +#include "xap_DefaultModuleFactory.h" #include "xap_Prefs.h" #include "ut_string_class.h" #include "ut_path.h" -// the loader manages instances of one of these target classes -#if defined (WIN32) - #include "xap_Win32Module.h" - #define MODULE_CLASS XAP_Win32Module - -#elif defined (__BEOS__) - #include "xap_BeOSModule.h" - #define MODULE_CLASS XAP_BeOSModule - -#elif defined (__QNXNTO__) - #include "xap_QNXModule.h" - #define MODULE_CLASS XAP_QNXModule - -#elif defined (__APPLE__) && defined (XP_MAC_TARGET_MACOSX) - #if defined (XP_MAC_TARGET_CARBON) - #include - #if defined(TARGET_RT_MAC_CFM) && (TARGET_RT_MAC_CFM == 1) - #include "xap_MacCFMModule.h" - #define MODULE_CLASS XAP_MacModule - #elif defined (TARGET_RT_MAC_MACHO) && (TARGET_RT_MAC_MACHO == 1) - #include "xap_MacModule.h" - #define MODULE_CLASS XAP_MacModule - #else - #error Unknown Apple architecture - #endif - #elif defined (XP_TARGET_COCOA) - #include "xap_CocoaModule.h" - #define MODULE_CLASS XAP_CocoaModule - #endif -#else - // *NIX - #include "xap_UnixModule.h" - #define MODULE_CLASS XAP_UnixModule +// todo +#undef UT_DEBUGMSG +#define UT_DEBUGMSG(M) printf M -#endif // log information about plugin loading into the section of AbiWord.profile // (we save the prefs file after each call, so as to maximise the information we have in @@ -76,7 +47,7 @@ { \ UT_String __s; \ UT_String_sprintf(__s, "(L%d): %s %s", __LINE__, msg1, msg2); \ - UT_DEBUGMSG(("%s",__s.c_str())); \ + UT_DEBUGMSG(("%s\n",__s.c_str())); \ XAP_App::getApp()->getPrefs()->log("XAP_ModuleManager::loadModule", __s.c_str());\ XAP_App::getApp()->getPrefs()->savePrefsFile(); \ } @@ -85,8 +56,10 @@ * Protected destructor creates an instance of this module class */ XAP_ModuleManager::XAP_ModuleManager () : - m_spider(new XAP_Spider) + m_spider (new XAP_Spider), + m_defaultFactory (new XAP_DefaultModuleFactory) { + m_factories = new UT_GenericVector (1); m_modules = new UT_GenericVector (11); } @@ -96,8 +69,15 @@ XAP_ModuleManager::~XAP_ModuleManager () { DELETEP (m_spider); - UT_VECTOR_PURGEALL (MODULE_CLASS *, (*m_modules)); + DELETEP (m_defaultFactory); + + UT_VECTOR_PURGEALL (XAP_Module *, (*m_modules)); delete m_modules; + m_modules = NULL; + + UT_VECTOR_PURGEALL (XAP_ModuleFactory *, (*m_factories)); + delete m_factories; + m_factories = NULL; } /*! @@ -110,6 +90,61 @@ } /*! +* Register a new plugin factory. +* When a plugin is to be loaded all registered factories try loading +* it before the default implementation XAP_ModuleManager::loadModule() is invoked. +* \param pFactory Ptr to factory instance +* \see XAP_ModuleManager::loadModule() +* \see XAP_ModuleFactory::loadModule() +*/ +bool +XAP_ModuleManager::registerFactory (XAP_ModuleFactory * pFactory) +{ + UT_sint32 ndx = m_factories->findItem (pFactory); + if (ndx > 0) { + // already loaded + return FALSE; + } + m_factories->addItem (pFactory); + return TRUE; +} + +/*! +* Remove a plugged factory. +* \param pFactory Ptr to factory instance +*/ +bool +XAP_ModuleManager::unregisterFactory (XAP_ModuleFactory * pFactory) +{ + UT_return_val_if_fail(m_modules != NULL, FALSE); + UT_return_val_if_fail(m_factories != NULL, FALSE); + + UT_sint32 ndx = m_factories->findItem (pFactory); + if (ndx < 0) { + return FALSE; + } + + // unload all plugins loaded by this factory + UT_uint32 count = m_modules->size (); + XAP_Module * pModule = NULL; + for (UT_uint32 i = 0; i < count; i++) { + pModule = m_modules->getNthItem (i); + if (pModule != NULL /* we have a module */ + && pModule->getCreator () == pFactory) { /* the module has been loaded by the factory in question */ + + unloadModule (pModule); + + // restart loop, don't assume anything about the vectors internal order + count = m_modules->size (); + i = 0; + } + } + + m_factories->deleteNthItem (ndx); + return TRUE; +} + +/*! * Request that the ModuleManager load the module represented by szFilename. * * \param szFilename - the .dll or .so on your system that you wish to load @@ -119,17 +154,16 @@ * * \return true if loaded (and, if not a SPI, registered) successfully, false otherwise */ -bool XAP_ModuleManager::loadModule (const char * szFilename) +XAP_Module * +XAP_ModuleManager::loadModule (const char * szFilename) { - UT_ASSERT (szFilename); - - if ( szFilename == 0) return false; - if (*szFilename == 0) return false; - + UT_return_val_if_fail(m_modules != NULL, FALSE); + UT_return_val_if_fail(m_spider != NULL, FALSE); XAP_MODULE_MANAGER_LOAD_LOG("loading", szFilename) + XAP_Module * pModule = NULL; + // check to see if plugin is already loaded - XAP_Module* pModuleLoop = 0; const UT_GenericVector *pVec = enumModules(); @@ -144,81 +178,64 @@ { // already loaded, don't attempt to load again and exit quietly FREEP(moduleName); - return true; + return pModuleLoop; } FREEP(moduleName); } } + XAP_ModuleFactory * pFactory = NULL; + pModule = _factoryLoadModule (szFilename, pFactory); - XAP_Module * pModule = 0; - UT_TRY - { - pModule = new MODULE_CLASS; - } - UT_CATCH (...) - { - pModule = 0; - } - if (pModule == 0) return false; - - if (!pModule->load (szFilename)) - { - UT_DEBUGMSG (("Failed to load module %s\n", szFilename)); - XAP_MODULE_MANAGER_LOAD_LOG("failed to load", szFilename) - - char * errorMsg = 0; - if (pModule->getErrorMsg (&errorMsg)) - { - UT_DEBUGMSG (("Reason: %s\n", errorMsg)); - XAP_MODULE_MANAGER_LOAD_LOG("error msg", errorMsg) - FREEP (errorMsg); - } - delete pModule; - return false; - } - - /* assign the module's creator to be us, etc. - */ + // assign the module's creator to be us, etc. pModule->setSpider (m_spider); pModule->setLoaded (true); - pModule->setCreator (this); + pModule->setCreator (pFactory); + + bool bInitialized = pModule->registerThySelf (); + if (!bInitialized) { - if (!pModule->registerThySelf ()) - { - UT_DEBUGMSG (("Failed to register module %s\n", szFilename)); XAP_MODULE_MANAGER_LOAD_LOG("failed to register", szFilename) char * errorMsg = 0; if (pModule->getErrorMsg (&errorMsg)) { - UT_DEBUGMSG (("Reason: %s\n", errorMsg)); XAP_MODULE_MANAGER_LOAD_LOG("error msg", errorMsg) FREEP (errorMsg); } - pModule->unload (); - delete pModule; - return false; } - if (m_modules->addItem (pModule)) // an error occurred... - { + else if (m_modules->addItem (pModule)) { + // an error occurred... XAP_MODULE_MANAGER_LOAD_LOG("could not add", szFilename) pModule->unregisterThySelf (); - pModule->unload (); - delete pModule; - return false; + bInitialized = FALSE; + } + else { + UT_String msg = "success ("; + msg += pFactory->getName (); + msg += ") "; + XAP_MODULE_MANAGER_LOAD_LOG(msg.c_str (), szFilename) + } + + // clean up if no success + if (!bInitialized) { + unloadModule (pModule); + pModule = NULL; + return NULL; } + /* we (somehow :^) got here. count our blessings and return */ - XAP_MODULE_MANAGER_LOAD_LOG("success", szFilename) - return true; + return pModule; } bool XAP_ModuleManager::loadPreloaded (XAP_Plugin_Registration fnRegister, XAP_Plugin_Registration fnDeregister, XAP_Plugin_VersionCheck fnSupportsVersion) { + UT_return_val_if_fail(m_modules != NULL, FALSE); + UT_return_val_if_fail(m_spider != NULL, FALSE); UT_ASSERT (fnRegister && fnDeregister && fnSupportsVersion); if (!(fnRegister && fnDeregister && fnSupportsVersion)) return false; @@ -226,7 +243,7 @@ XAP_Module * pModule = 0; UT_TRY { - pModule = new MODULE_CLASS; + pModule = m_defaultFactory->newModule (); } UT_CATCH (...) { @@ -244,7 +261,7 @@ */ pModule->setSpider (m_spider); pModule->setLoaded (true); - pModule->setCreator (this); + pModule->setCreator (m_defaultFactory); if (!pModule->registerThySelf ()) { @@ -274,6 +291,8 @@ */ UT_uint32 XAP_ModuleManager::registerPending () { + UT_return_val_if_fail(m_modules != NULL, 0); + UT_uint32 count = 0; if (m_spider) count = m_spider->register_spies (); @@ -304,23 +323,22 @@ * Don't assume anything, therefore, about the UT_Vector returned by * XAP_ModuleManager::enumModules */ -void XAP_ModuleManager::unloadModule (XAP_Module * pModule) +bool +XAP_ModuleManager::unloadModule (XAP_Module * pModule) { - UT_ASSERT (pModule); - if (pModule == 0) return; - - UT_ASSERT (pModule->getCreator () == this); - if (pModule->getCreator () != this) return; + UT_return_val_if_fail(m_modules != NULL, FALSE); + UT_return_val_if_fail(pModule != NULL, FALSE); UT_sint32 ndx = m_modules->findItem (pModule); if (ndx == -1) { UT_ASSERT (UT_SHOULD_NOT_HAPPEN); UT_DEBUGMSG (("Could not unload module\n")); - return; + return FALSE; } unloadModule (ndx); unloadUnregistered (); + return TRUE; } /* for use by unloadAllPlugins, unloadModule & unloadUnregistered only! @@ -333,21 +351,10 @@ m_modules->deleteNthItem (ndx); - // we're less picky when unloading than we are when loading - // the (necessarily true) assumptions are that - // - // 1) we were the one who loaded the module - // 2) registerThySelf() worked - // - // so it had better damn well work in the opposite direction! - - pModule->unregisterThySelf (); - pModule->setLoaded (false); - - bool module_unloaded = pModule->unload (); - UT_ASSERT (module_unloaded == true); - - delete pModule; + bool bUnloaded = _factoryUnloadModule (pModule); + + UT_DEBUGMSG (("ROB: unloaded '%d'\n", bUnloaded)); + UT_ASSERT (bUnloaded == true); } /*! @@ -382,6 +389,8 @@ */ const UT_GenericVector * XAP_ModuleManager::enumModules () const { + UT_return_val_if_fail(m_modules != NULL, NULL); + // TODO: perhaps we should clone this return m_modules; } @@ -411,3 +420,90 @@ } } } + +/*! +* Tells if a module has been loaded by the builtin factory. +* \param pModule Ptr to module instance. +*/ +bool +XAP_ModuleManager::loadedByDefaultFactory (const XAP_Module * pModule) +{ + return pModule->getCreator () == m_defaultFactory; +} + +/*! +* Iterate through the loaded plugin factories if any wants to load the plugin szFilename. +* \param szFilename File containing the plugin (shared object) +* \param pFactory Plugin factory to pass back if one bites +*/ +XAP_Module * +XAP_ModuleManager::_factoryLoadModule (const char * szFilename, + XAP_ModuleFactory *& pFactory) +{ + UT_return_val_if_fail(m_modules != NULL, NULL); + UT_return_val_if_fail (szFilename != NULL, NULL); + + XAP_Module * pModule = NULL; + + // load plugin using plugged loader + UT_uint32 count = m_factories->size (); + for (UT_uint32 i = 0; i < count; i++) { + XAP_ModuleFactory * pFactoryLoop = m_factories->getNthItem (i); + pModule = pFactoryLoop->loadModule (szFilename); + if (pModule != NULL) { + pFactory = pFactoryLoop; + UT_String msg; + UT_String_sprintf ("successfully loaded by '%s'\n", pFactoryLoop->getName ()); + XAP_MODULE_MANAGER_LOAD_LOG (msg.c_str (), szFilename); + break; + } + else { + UT_DEBUGMSG (("ROB: Factory '%s' rejected loading '%s'\n", pFactoryLoop->getName (), szFilename)); + } + } + + // load plugin using default loader + if (pModule == NULL) { + pModule = m_defaultFactory->loadModule (szFilename); + pFactory = m_defaultFactory; + } + + return pModule; +} + +/*! +* Iterate through the loaded plugin factories if any wants to unload the plugin itself. +* \param pModule Module to unload +* \return TRUE on success, FALSE if not yet unloaded. +*/ +bool +XAP_ModuleManager::_factoryUnloadModule (XAP_Module * pModule) +{ + bool bUnloaded = FALSE; + char * szName = NULL; + pModule->getModuleName(&szName); + UT_DEBUGMSG (("XAP_ModuleManager::_factoryUnloadModule () '%s' ('%d')\n", szName, (int)pModule)); + + // let's see if any the plugged factories feels responsible + UT_uint32 count = m_factories->size (); + for (UT_uint32 i = 0; i < count; i++) { + XAP_ModuleFactory * pFactoryLoop = m_factories->getNthItem (i); + bUnloaded = pFactoryLoop->unloadModule (pModule); + if (bUnloaded) { + UT_DEBUGMSG (("Factory '%s' unloaded module '%s'\n", pFactoryLoop->getName (), szName)); + FREEP (szName); + return TRUE; + } + else { + UT_DEBUGMSG (("Factory '%s' rejected undloading module '%s'\n", pFactoryLoop->getName (), szName)); + } + } + + // load plugin using default unloader + if (!bUnloaded) { + bUnloaded = m_defaultFactory->unloadModule (pModule); + } + + FREEP (szName); + return bUnloaded; +} Index: xp/xap_ModuleManager.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_ModuleManager.h,v retrieving revision 1.11 diff -a -u -r1.11 xap_ModuleManager.h --- xp/xap_ModuleManager.h 23 Mar 2004 00:12:12 -0000 1.11 +++ xp/xap_ModuleManager.h 4 Feb 2005 09:41:00 -0000 @@ -35,32 +35,38 @@ #include "ut_vector.h" +#include "xap_ModuleFactory.h" #include "xap_Module.h" class XAP_Spider; +class XAP_DefaultModuleFactory; + class ABI_EXPORT XAP_ModuleManager { - friend class XAP_Module; private: XAP_ModuleManager (); public: - ~XAP_ModuleManager (); // grrr + virtual ~XAP_ModuleManager (); // grrr static XAP_ModuleManager & instance (); - bool loadModule (const char * szFilename); + bool registerFactory (XAP_ModuleFactory * factory); + bool unregisterFactory (XAP_ModuleFactory * factory); + + XAP_Module * loadModule (const char * szFilename); bool loadPreloaded (XAP_Plugin_Registration fnRegister, XAP_Plugin_Registration fnDeregister, XAP_Plugin_VersionCheck fnSupportsVersion); UT_uint32 registerPending (); + bool loadedByDefaultFactory (const XAP_Module * pModule); - void unloadModule (XAP_Module * module); + bool unloadModule (XAP_Module * module); private: void unloadModule (UT_sint32 ndx); public: @@ -71,11 +77,17 @@ private: + XAP_Module * _factoryLoadModule (const char * szFilename, + XAP_ModuleFactory *& pFactory); + bool _factoryUnloadModule (XAP_Module * pModule); + XAP_ModuleManager(const XAP_ModuleManager &); // no impl void operator=(const XAP_ModuleManager &); // no impl XAP_Spider * m_spider; + XAP_DefaultModuleFactory * m_defaultFactory; + UT_GenericVector * m_factories; UT_GenericVector * m_modules; };