Index: af/xap/unix/xap_UnixModule.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/unix/xap_UnixModule.h,v retrieving revision 1.6 diff -u -r1.6 xap_UnixModule.h --- af/xap/unix/xap_UnixModule.h 12 Sep 2001 17:51:44 -0000 1.6 +++ af/xap/unix/xap_UnixModule.h 2 Feb 2005 17:23:30 -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: af/xap/xp/xap_Module.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_Module.h,v retrieving revision 1.27 diff -u -r1.27 xap_Module.h --- af/xap/xp/xap_Module.h 16 Jun 2003 17:14:11 -0000 1.27 +++ af/xap/xp/xap_Module.h 2 Feb 2005 17:23:31 -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); @@ -71,16 +72,16 @@ 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 +96,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 +117,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 +128,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: af/xap/xp/xap_ModuleManager.cpp =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_ModuleManager.cpp,v retrieving revision 1.25 diff -u -r1.25 xap_ModuleManager.cpp --- af/xap/xp/xap_ModuleManager.cpp 13 Dec 2004 17:38:02 -0000 1.25 +++ af/xap/xp/xap_ModuleManager.cpp 2 Feb 2005 17:23:33 -0000 @@ -31,6 +31,10 @@ #include "ut_string_class.h" #include "ut_path.h" +// todo +#undef UT_DEBUGMSG +#define UT_DEBUGMSG(M) printf M + // the loader manages instances of one of these target classes #if defined (WIN32) @@ -76,7 +80,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(); \ } @@ -87,6 +91,7 @@ XAP_ModuleManager::XAP_ModuleManager () : m_spider(new XAP_Spider) { + m_factories = new UT_GenericVector (1); m_modules = new UT_GenericVector (11); } @@ -96,8 +101,14 @@ XAP_ModuleManager::~XAP_ModuleManager () { DELETEP (m_spider); + UT_VECTOR_PURGEALL (MODULE_CLASS *, (*m_modules)); delete m_modules; + m_modules = NULL; + + UT_VECTOR_PURGEALL (XAP_ModuleFactory *, (*m_factories)); + delete m_factories; + m_factories = NULL; } /*! @@ -110,6 +121,56 @@ } /*! +* 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. +* \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. +*/ +bool +XAP_ModuleManager::unregisterFactory (XAP_ModuleFactory * pFactory) +{ + 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,15 +180,19 @@ * * \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; + if ( szFilename == 0) return NULL; + if (*szFilename == 0) return NULL; XAP_MODULE_MANAGER_LOAD_LOG("loading", szFilename) + XAP_Module * pModule = NULL; + XAP_ModuleFactory *pFactory = this; + // check to see if plugin is already loaded XAP_Module* pModuleLoop = 0; @@ -144,75 +209,87 @@ { // already loaded, don't attempt to load again and exit quietly FREEP(moduleName); - return true; + return pModuleLoop; } FREEP(moduleName); } } + // let's see if any the plugged factories feels responsible + pModule = _factoryLoadModule (szFilename, pFactory); - XAP_Module * pModule = 0; - UT_TRY - { - pModule = new MODULE_CLASS; - } - UT_CATCH (...) - { - pModule = 0; - } - if (pModule == 0) return false; + // load plugin using default impl + if (pModule == NULL) { + + UT_TRY { + pModule = new MODULE_CLASS; + } + UT_CATCH (...) { + pModule = 0; + } + if (pModule == 0) return NULL; - if (!pModule->load (szFilename)) - { - UT_DEBUGMSG (("Failed to load module %s\n", szFilename)); - XAP_MODULE_MANAGER_LOAD_LOG("failed to load", szFilename) + if (!pModule->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); + XAP_MODULE_MANAGER_LOAD_LOG("failed to load", szFilename) + + char * errorMsg = 0; + if (pModule->getErrorMsg (&errorMsg)) { + + XAP_MODULE_MANAGER_LOAD_LOG("error msg", errorMsg) + FREEP (errorMsg); + } + delete pModule; + return NULL; } - delete pModule; - return false; + } /* assign the module's creator to be us, etc. */ + bool bInitialized = FALSE; pModule->setSpider (m_spider); pModule->setLoaded (true); - pModule->setCreator (this); + pModule->setCreator (pFactory); + + 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) { + if (!_factoryUnloadModule (pModule)) { + pModule->unload (); + delete 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, @@ -304,23 +381,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; + if (pModule == 0) return 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 +409,27 @@ 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! + // let's see if any the plugged factories feels responsible + bool bUnloaded = _factoryUnloadModule (pModule); - pModule->unregisterThySelf (); - pModule->setLoaded (false); + if (!bUnloaded) { - bool module_unloaded = pModule->unload (); - UT_ASSERT (module_unloaded == true); + // 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! - delete pModule; + pModule->unregisterThySelf (); + pModule->setLoaded (false); + + bUnloaded = pModule->unload (); + delete pModule; + pModule = NULL; + } + + UT_DEBUGMSG (("ROB: unloaded '%d'\n", bUnloaded)); + UT_ASSERT (bUnloaded == true); } /*! @@ -411,3 +493,65 @@ } } } + +/*! +* 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 (szFilename != NULL, NULL); + + XAP_Module * pModule = NULL; + + 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)); + } + } + 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)); + + 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)); + } + } + + FREEP (szName); + return bUnloaded; +} Index: af/xap/xp/xap_ModuleManager.h =================================================================== RCS file: /cvsroot/abi/src/af/xap/xp/xap_ModuleManager.h,v retrieving revision 1.11 diff -u -r1.11 xap_ModuleManager.h --- af/xap/xp/xap_ModuleManager.h 23 Mar 2004 00:12:12 -0000 1.11 +++ af/xap/xp/xap_ModuleManager.h 2 Feb 2005 17:23:33 -0000 @@ -35,12 +35,13 @@ #include "ut_vector.h" +#include "xap_ModuleFactory.h" #include "xap_Module.h" class XAP_Spider; -class ABI_EXPORT XAP_ModuleManager +class ABI_EXPORT XAP_ModuleManager : public XAP_ModuleFactory { friend class XAP_Module; @@ -48,11 +49,15 @@ XAP_ModuleManager (); public: - ~XAP_ModuleManager (); // grrr + virtual ~XAP_ModuleManager (); // grrr static XAP_ModuleManager & instance (); - bool loadModule (const char * szFilename); + const char * getName (void) { return "Default Factory"; } + 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, @@ -60,7 +65,7 @@ UT_uint32 registerPending (); - void unloadModule (XAP_Module * module); + bool unloadModule (XAP_Module * module); private: void unloadModule (UT_sint32 ndx); public: @@ -71,11 +76,16 @@ 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; + UT_GenericVector * m_factories; UT_GenericVector * m_modules; };