X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FConfig%2FConfig_ModuleReader.cpp;h=9e8549cdb43bd7d7aea303add9f452ed95bf922c;hb=bdbfb368d71ed11cc0391354a7d86c880cd94949;hp=6153bd04dc727f5f761b870d6879f8e831a7edb1;hpb=d4d5684c9088ac4fea8411b62e10a277729c75fa;p=modules%2Fshaper.git diff --git a/src/Config/Config_ModuleReader.cpp b/src/Config/Config_ModuleReader.cpp index 6153bd04d..9e8549cdb 100644 --- a/src/Config/Config_ModuleReader.cpp +++ b/src/Config/Config_ModuleReader.cpp @@ -1,3 +1,5 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + /* * Config_ModuleReader.cpp * @@ -5,22 +7,37 @@ * Author: sbh */ +#include + #include #include #include #include +#include #include #include -#ifdef _DEBUG +// Have to be included before std headers +#include + +//Necessary for cerr #include -#endif +#include +#ifdef WIN32 +#include +#pragma warning(disable : 4996) // for getenv +#else +#include +#endif +std::map Config_ModuleReader::myPluginTypes; +std::set Config_ModuleReader::myDependencyModules; Config_ModuleReader::Config_ModuleReader(const char* theEventGenerated) - : Config_XMLReader("plugins.xml"), myIsAutoImport(false), myEventGenerated(theEventGenerated) + : Config_XMLReader(PLUGIN_FILE), + myEventGenerated(theEventGenerated) { } @@ -28,7 +45,17 @@ Config_ModuleReader::~Config_ModuleReader() { } -/* +const std::map& Config_ModuleReader::featuresInFiles() const +{ + return myFeaturesInFiles; +} + +const std::set& Config_ModuleReader::modulePluginFiles() const +{ + return myPluginFiles; +} + +/*! * Get module name from plugins.xml * (property "module") */ @@ -38,17 +65,38 @@ std::string Config_ModuleReader::getModuleName() return getProperty(aRoot, PLUGINS_MODULE); } -/* - * - */ + +void Config_ModuleReader::addFeature(const std::string& theFeatureName, + const std::string& thePluginConfig) +{ + if (myFeaturesInFiles.count(theFeatureName)) { + std::string anErrorMsg = "Can not register feature '%1' in plugin '%2'." + " There is a feature with the same ID."; + Events_InfoMessage("Config_ModuleReader", anErrorMsg) + .arg(theFeatureName).arg(thePluginConfig).send(); + return; + } + + myFeaturesInFiles[theFeatureName] = thePluginConfig; +} + void Config_ModuleReader::processNode(xmlNodePtr theNode) { if (isNode(theNode, NODE_PLUGIN, NULL)) { + if (!hasRequiredModules(theNode)) + return; std::string aPluginConf = getProperty(theNode, PLUGIN_CONFIG); + if (!aPluginConf.empty()) + myPluginFiles.insert(aPluginConf); std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY); - if (myIsAutoImport) - importPlugin(aPluginConf, aPluginLibrary); - myPluginsMap[aPluginLibrary] = aPluginConf; + std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT); + std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf); + + std::list aFeatures = importPlugin(aPluginName, aPluginConf); + std::list::iterator it = aFeatures.begin(); + for (; it != aFeatures.end(); it++) { + addFeature(*it, aPluginConf); + } } } @@ -57,24 +105,138 @@ bool Config_ModuleReader::processChildren(xmlNodePtr theNode) return isNode(theNode, NODE_PLUGINS, NULL); } -void Config_ModuleReader::importPlugin(const std::string& thePluginName, - const std::string& thePluginLibrary) +bool Config_ModuleReader::hasRequiredModules(xmlNodePtr theNode) const +{ + std::string aRequiredModule = normalize(getProperty(theNode, PLUGIN_DEPENDENCY)); + if(aRequiredModule.empty()) + return true; + std::set::iterator it = myDependencyModules.begin(); + for ( ; it != myDependencyModules.end(); it++ ) { + if (*it == aRequiredModule) return true; + } + return false; +} + +std::list Config_ModuleReader::importPlugin(const std::string& thePluginLibrary, + const std::string& thePluginXmlConf) { - Config_FeatureReader* aReader; - if(thePluginLibrary.empty()) { - aReader = new Config_FeatureReader(thePluginName); - } else { - aReader = new Config_FeatureReader(thePluginName, thePluginLibrary, myEventGenerated); + if (thePluginXmlConf.empty()) { //probably a third party library + loadLibrary(thePluginLibrary); + return std::list(); } - aReader->readAll(); + + Config_FeatureReader aReader = Config_FeatureReader(thePluginXmlConf, + thePluginLibrary, + myEventGenerated); + aReader.readAll(); + return aReader.features(); } -void Config_ModuleReader::setAutoImport(bool theEnabled) +std::string Config_ModuleReader::addPlugin(const std::string& aPluginLibrary, + const std::string& aPluginScript, + const std::string& aPluginConf) { - myIsAutoImport = theEnabled; + PluginType aType = Config_ModuleReader::Binary; + std::string aPluginName; + if (!aPluginLibrary.empty()) { + aPluginName = aPluginLibrary; + if (aPluginConf.empty()) { + aType = Config_ModuleReader::Intrenal; + } + } else if (!aPluginScript.empty()) { + aPluginName = aPluginScript; + aType = Config_ModuleReader::Python; + } + if(!aPluginName.empty()) { + myPluginTypes[aPluginName] = aType; + } + addDependencyModule(aPluginName); + return aPluginName; } -const std::map& Config_ModuleReader::plugins() const +void Config_ModuleReader::loadPlugin(const std::string& thePluginName) { - return myPluginsMap; + PluginType aType = Config_ModuleReader::Binary; + if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) { + aType = myPluginTypes.at(thePluginName); + } + switch (aType) { + case Config_ModuleReader::Python: + loadScript(thePluginName); + break; + case Config_ModuleReader::Binary: + case Config_ModuleReader::Intrenal: + default: + loadLibrary(thePluginName); + break; + } } + +void Config_ModuleReader::loadScript(const std::string& theFileName, bool theSendErr) +{ + /* acquire python thread */ + PyGILState_STATE gstate = PyGILState_Ensure(); + + PyObject* module = PyImport_ImportModule(theFileName.c_str()); + if (!module) { + std::string anErrorMsg = "An error occurred while importing " + theFileName; + //Get detailed error message: + if (PyErr_Occurred()) { + PyObject *pstr, *ptype, *pvalue, *ptraceback; + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); + pstr = PyObject_Str(pvalue); + std::string aPyError = std::string(PyString_AsString(pstr)); + if (!aPyError.empty()) { + anErrorMsg += ":\n" + aPyError; + } + Py_XDECREF(pstr); + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + } + if (theSendErr) + Events_InfoMessage("Config_ModuleReader", anErrorMsg).send(); + } + + /* release python thread */ + PyGILState_Release(gstate); +} + +void Config_ModuleReader::loadLibrary(const std::string& theLibName) +{ + std::string aFileName = library(theLibName); + if (aFileName.empty()) + return; + + #ifdef WIN32 + HINSTANCE aModLib = ::LoadLibrary(aFileName.c_str()); + #else + void* aModLib = dlopen( aFileName.c_str(), RTLD_LAZY | RTLD_GLOBAL ); + #endif + if(!aModLib && theLibName != "DFBrowser") { // don't show error for internal debugging tool + std::string anErrorMsg = "Failed to load " + aFileName; + #ifdef WIN32 + DWORD dwLastError = ::GetLastError(); + LPSTR messageBuffer = NULL; + size_t size = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwLastError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&messageBuffer, 0, NULL); + anErrorMsg += ": " + std::string(messageBuffer, size); + #else + anErrorMsg += ": " + std::string(dlerror()); + #endif + std::cerr << anErrorMsg << std::endl; + Events_InfoMessage("Config_ModuleReader", anErrorMsg).send(); + } +} + +void Config_ModuleReader::addDependencyModule(const std::string& theModuleName) +{ + myDependencyModules.insert(normalize(theModuleName)); +} +