MyGUI  3.2.1
MyGUI_PluginManager.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_PluginManager.h"
00009 #include "MyGUI_DynLibManager.h"
00010 #include "MyGUI_ResourceManager.h"
00011 
00012 namespace MyGUI
00013 {
00014 
00015     typedef void (*DLL_START_PLUGIN)(void);
00016     typedef void (*DLL_STOP_PLUGIN)(void);
00017 
00018     template <> PluginManager* Singleton<PluginManager>::msInstance = nullptr;
00019     template <> const char* Singleton<PluginManager>::mClassTypeName = "PluginManager";
00020 
00021     PluginManager::PluginManager() :
00022         mIsInitialise(false),
00023         mXmlPluginTagName("Plugin")
00024     {
00025     }
00026 
00027     void PluginManager::initialise()
00028     {
00029         MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
00030         MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
00031 
00032         ResourceManager::getInstance().registerLoadXmlDelegate(mXmlPluginTagName) = newDelegate(this, &PluginManager::_load);
00033 
00034         MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
00035         mIsInitialise = true;
00036     }
00037 
00038     void PluginManager::shutdown()
00039     {
00040         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
00041         MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());
00042 
00043         unloadAllPlugins();
00044         ResourceManager::getInstance().unregisterLoadXmlDelegate(mXmlPluginTagName);
00045 
00046         MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
00047         mIsInitialise = false;
00048     }
00049 
00050     bool PluginManager::loadPlugin(const std::string& _file)
00051     {
00052         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00053 
00054         // Load plugin library
00055         DynLib* lib = DynLibManager::getInstance().load(_file);
00056         if (!lib)
00057         {
00058             MYGUI_LOG(Error, "Plugin '" << _file << "' not found");
00059             return false;
00060         }
00061 
00062         // Call startup function
00063         DLL_START_PLUGIN pFunc = reinterpret_cast<DLL_START_PLUGIN>(lib->getSymbol("dllStartPlugin"));
00064         if (!pFunc)
00065         {
00066             MYGUI_LOG(Error, "Cannot find symbol 'dllStartPlugin' in library " << _file);
00067             return false;
00068         }
00069 
00070         // Store for later unload
00071         mLibs[_file] = lib;
00072 
00073         // This must call installPlugin
00074         pFunc();
00075 
00076         return true;
00077     }
00078 
00079     void PluginManager::unloadPlugin(const std::string& _file)
00080     {
00081         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00082 
00083         DynLibList::iterator it = mLibs.find(_file);
00084         if (it != mLibs.end())
00085         {
00086             // Call plugin shutdown
00087             DLL_STOP_PLUGIN pFunc = reinterpret_cast<DLL_STOP_PLUGIN>((*it).second->getSymbol("dllStopPlugin"));
00088 
00089             MYGUI_ASSERT(nullptr != pFunc, getClassTypeName() << "Cannot find symbol 'dllStopPlugin' in library " << _file);
00090 
00091             // this must call uninstallPlugin
00092             pFunc();
00093             // Unload library (destroyed by DynLibManager)
00094             DynLibManager::getInstance().unload((*it).second);
00095             mLibs.erase(it);
00096         }
00097     }
00098 
00099     void PluginManager::_load(xml::ElementPtr _node, const std::string& _file, Version _version)
00100     {
00101         xml::ElementEnumerator node = _node->getElementEnumerator();
00102         while (node.next())
00103         {
00104             if (node->getName() == "path")
00105             {
00106                 std::string source;
00107                 if (node->findAttribute("source", source))
00108                     loadPlugin(source);
00109             }
00110             else if (node->getName() == "Plugin")
00111             {
00112                 std::string source;
00113 
00114                 xml::ElementEnumerator source_node = node->getElementEnumerator();
00115                 while (source_node.next("Source"))
00116                 {
00117                     std::string build = source_node->findAttribute("build");
00118 #if MYGUI_DEBUG_MODE == 1
00119                     if (build == "Debug")
00120                         source = source_node->getContent();
00121 #else
00122                     if (build != "Debug")
00123                         source = source_node->getContent();
00124 #endif
00125                 }
00126                 if (!source.empty())
00127                     loadPlugin(source);
00128             }
00129         }
00130     }
00131 
00132     void PluginManager::installPlugin(IPlugin* _plugin)
00133     {
00134         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00135 
00136         MYGUI_LOG(Info, "Installing plugin: " << _plugin->getName());
00137 
00138         mPlugins.insert(_plugin);
00139         _plugin->install();
00140 
00141         _plugin->initialize();
00142 
00143         MYGUI_LOG(Info, "Plugin successfully installed");
00144     }
00145 
00146     void PluginManager::uninstallPlugin(IPlugin* _plugin)
00147     {
00148         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00149 
00150         MYGUI_LOG(Info, "Uninstalling plugin: " << _plugin->getName());
00151         PluginList::iterator it = mPlugins.find(_plugin);
00152         if (it != mPlugins.end())
00153         {
00154             _plugin->shutdown();
00155             _plugin->uninstall();
00156             mPlugins.erase(it);
00157         }
00158         MYGUI_LOG(Info, "Plugin successfully uninstalled");
00159     }
00160 
00161     void PluginManager::unloadAllPlugins()
00162     {
00163         while (!mLibs.empty())
00164             unloadPlugin((*mLibs.begin()).first);
00165     }
00166 
00167 } // namespace MyGUI