MyGUI  3.2.0
MyGUI_PluginManager.cpp
Go to the documentation of this file.
00001 
00006 /*
00007     This file is part of MyGUI.
00008 
00009     MyGUI is free software: you can redistribute it and/or modify
00010     it under the terms of the GNU Lesser General Public License as published by
00011     the Free Software Foundation, either version 3 of the License, or
00012     (at your option) any later version.
00013 
00014     MyGUI is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00021 */
00022 #include "MyGUI_Precompiled.h"
00023 #include "MyGUI_PluginManager.h"
00024 #include "MyGUI_DynLibManager.h"
00025 #include "MyGUI_ResourceManager.h"
00026 
00027 namespace MyGUI
00028 {
00029     typedef void (*DLL_START_PLUGIN)(void);
00030     typedef void (*DLL_STOP_PLUGIN)(void);
00031 
00032     const std::string XML_TYPE("Plugin");
00033 
00034     template <> PluginManager* Singleton<PluginManager>::msInstance = nullptr;
00035     template <> const char* Singleton<PluginManager>::mClassTypeName("PluginManager");
00036 
00037     PluginManager::PluginManager() :
00038         mIsInitialise(false)
00039     {
00040     }
00041 
00042     void PluginManager::initialise()
00043     {
00044         MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
00045         MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
00046 
00047         ResourceManager::getInstance().registerLoadXmlDelegate(XML_TYPE) = newDelegate(this, &PluginManager::_load);
00048 
00049         MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
00050         mIsInitialise = true;
00051     }
00052 
00053     void PluginManager::shutdown()
00054     {
00055         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
00056         MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());
00057 
00058         unloadAllPlugins();
00059         ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);
00060 
00061         MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
00062         mIsInitialise = false;
00063     }
00064 
00065     bool PluginManager::loadPlugin(const std::string& _file)
00066     {
00067         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00068 
00069         // Load plugin library
00070         DynLib* lib = DynLibManager::getInstance().load(_file);
00071         if (!lib)
00072         {
00073             MYGUI_LOG(Error, "Plugin '" << _file << "' not found");
00074             return false;
00075         }
00076 
00077         // Call startup function
00078         DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
00079         if (!pFunc)
00080         {
00081             MYGUI_LOG(Error, "Cannot find symbol 'dllStartPlugin' in library " << _file);
00082             return false;
00083         }
00084 
00085         // Store for later unload
00086         mLibs[_file] = lib;
00087 
00088         // This must call installPlugin
00089         pFunc();
00090 
00091         return true;
00092     }
00093 
00094     void PluginManager::unloadPlugin(const std::string& _file)
00095     {
00096         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00097 
00098         DynLibList::iterator it = mLibs.find(_file);
00099         if (it != mLibs.end())
00100         {
00101             // Call plugin shutdown
00102             DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*it).second->getSymbol("dllStopPlugin");
00103 
00104             MYGUI_ASSERT(nullptr != pFunc, getClassTypeName() << "Cannot find symbol 'dllStopPlugin' in library " << _file);
00105 
00106             // this must call uninstallPlugin
00107             pFunc();
00108             // Unload library (destroyed by DynLibManager)
00109             DynLibManager::getInstance().unload((*it).second);
00110             mLibs.erase(it);
00111         }
00112     }
00113 
00114     void PluginManager::_load(xml::ElementPtr _node, const std::string& _file, Version _version)
00115     {
00116         xml::ElementEnumerator node = _node->getElementEnumerator();
00117         while (node.next())
00118         {
00119             if (node->getName() == "path")
00120             {
00121                 std::string source;
00122                 if (node->findAttribute("source", source))
00123                     loadPlugin(source);
00124             }
00125             else if (node->getName() == "Plugin")
00126             {
00127                 std::string source, source_debug;
00128 
00129                 xml::ElementEnumerator source_node = node->getElementEnumerator();
00130                 while (source_node.next("Source"))
00131                 {
00132                     std::string build = source_node->findAttribute("build");
00133                     if (build == "Debug")
00134                         source_debug = source_node->getContent();
00135                     else
00136                         source = source_node->getContent();
00137                 }
00138 #if MYGUI_DEBUG_MODE == 0
00139                 if (!source.empty())
00140                     loadPlugin(source);
00141 #else
00142                 if (!source_debug.empty())
00143                     loadPlugin(source_debug);
00144 #endif
00145             }
00146         }
00147     }
00148 
00149     void PluginManager::installPlugin(IPlugin* _plugin)
00150     {
00151         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00152 
00153         MYGUI_LOG(Info, "Installing plugin: " << _plugin->getName());
00154 
00155         mPlugins.insert(_plugin);
00156         _plugin->install();
00157 
00158         _plugin->initialize();
00159 
00160         MYGUI_LOG(Info, "Plugin successfully installed");
00161     }
00162 
00163     void PluginManager::uninstallPlugin(IPlugin* _plugin)
00164     {
00165         MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " used but not initialised");
00166 
00167         MYGUI_LOG(Info, "Uninstalling plugin: " << _plugin->getName());
00168         PluginList::iterator it = mPlugins.find(_plugin);
00169         if (it != mPlugins.end())
00170         {
00171             _plugin->shutdown();
00172             _plugin->uninstall();
00173             mPlugins.erase(it);
00174         }
00175         MYGUI_LOG(Info, "Plugin successfully uninstalled");
00176     }
00177 
00178     void PluginManager::unloadAllPlugins()
00179     {
00180         while (!mLibs.empty())
00181             unloadPlugin((*mLibs.begin()).first);
00182     }
00183 
00184 } // namespace MyGUI