1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
4 * Config_ModuleReader.cpp
6 * Created on: Mar 20, 2014
10 #include <Config_Keywords.h>
11 #include <Config_Common.h>
12 #include <Config_ModuleReader.h>
13 #include <Config_FeatureReader.h>
14 #include <Events_Error.h>
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
19 // Have to be included before std headers
28 #pragma warning(disable : 4996) // for getenv
33 std::map<std::string, Config_ModuleReader::PluginType> Config_ModuleReader::myPluginTypes;
34 std::set<std::string> Config_ModuleReader::myDependencyModules;
36 Config_ModuleReader::Config_ModuleReader(const char* theEventGenerated)
37 : Config_XMLReader(PLUGIN_FILE),
38 myEventGenerated(theEventGenerated)
42 Config_ModuleReader::~Config_ModuleReader()
46 const std::map<std::string, std::string>& Config_ModuleReader::featuresInFiles() const
48 return myFeaturesInFiles;
51 const std::set<std::string>& Config_ModuleReader::modulePluginFiles() const
57 * Get module name from plugins.xml
60 std::string Config_ModuleReader::getModuleName()
62 xmlNodePtr aRoot = findRoot();
63 return getProperty(aRoot, PLUGINS_MODULE);
66 void Config_ModuleReader::processNode(xmlNodePtr theNode)
68 if (isNode(theNode, NODE_PLUGIN, NULL)) {
69 if (!hasRequiredModules(theNode))
71 std::string aPluginConf = getProperty(theNode, PLUGIN_CONFIG);
72 if (!aPluginConf.empty()) myPluginFiles.insert(aPluginConf);
73 std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY);
74 std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT);
75 std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf);
77 std::list<std::string> aFeatures = importPlugin(aPluginName, aPluginConf);
78 std::list<std::string>::iterator it = aFeatures.begin();
79 for (; it != aFeatures.end(); it++) {
80 myFeaturesInFiles[*it] = aPluginConf;
85 bool Config_ModuleReader::processChildren(xmlNodePtr theNode)
87 return isNode(theNode, NODE_PLUGINS, NULL);
90 bool Config_ModuleReader::hasRequiredModules(xmlNodePtr theNode) const
92 std::string aRequiredModule = normalize(getProperty(theNode, PLUGIN_DEPENDENCY));
93 if(aRequiredModule.empty())
95 std::set<std::string>::iterator it = myDependencyModules.begin();
96 for ( ; it != myDependencyModules.end(); it++ ) {
97 if (*it == aRequiredModule) return true;
102 std::list<std::string> Config_ModuleReader::importPlugin(const std::string& thePluginLibrary,
103 const std::string& thePluginXmlConf)
105 if (thePluginXmlConf.empty()) { //probably a third party library
106 loadLibrary(thePluginLibrary);
107 return std::list<std::string>();
110 Config_FeatureReader aReader = Config_FeatureReader(thePluginXmlConf,
114 return aReader.features();
117 std::string Config_ModuleReader::addPlugin(const std::string& aPluginLibrary,
118 const std::string& aPluginScript,
119 const std::string& aPluginConf)
121 PluginType aType = Config_ModuleReader::Binary;
122 std::string aPluginName;
123 if (!aPluginLibrary.empty()) {
124 aPluginName = aPluginLibrary;
125 if (aPluginConf.empty()) {
126 aType = Config_ModuleReader::Intrenal;
128 } else if (!aPluginScript.empty()) {
129 aPluginName = aPluginScript;
130 aType = Config_ModuleReader::Python;
132 if(!aPluginName.empty()) {
133 myPluginTypes[aPluginName] = aType;
135 addDependencyModule(aPluginName);
139 void Config_ModuleReader::loadPlugin(const std::string& thePluginName)
141 PluginType aType = Config_ModuleReader::Binary;
142 if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) {
143 aType = myPluginTypes.at(thePluginName);
146 case Config_ModuleReader::Python:
147 loadScript(thePluginName);
149 case Config_ModuleReader::Binary:
150 case Config_ModuleReader::Intrenal:
152 loadLibrary(thePluginName);
157 void Config_ModuleReader::loadScript(const std::string& theFileName)
159 /* aquire python thread */
160 PyGILState_STATE gstate = PyGILState_Ensure();
162 PyObject* module = PyImport_ImportModule(theFileName.c_str());
164 std::string anErrorMsg = "An error occured while importing " + theFileName;
165 //Get detailed error message:
166 if (PyErr_Occurred()) {
167 PyObject *pstr, *ptype, *pvalue, *ptraceback;
168 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
169 PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
170 pstr = PyObject_Str(pvalue);
171 std::string aPyError = std::string(PyString_AsString(pstr));
172 if (!aPyError.empty()) {
173 anErrorMsg += ":\n" + aPyError;
178 Py_XDECREF(ptraceback);
180 Events_Error::send(anErrorMsg);
183 /* release python thread */
184 PyGILState_Release(gstate);
187 void Config_ModuleReader::loadLibrary(const std::string& theLibName)
189 std::string aFileName = library(theLibName);
190 if (aFileName.empty())
194 HINSTANCE aModLib = ::LoadLibrary(aFileName.c_str());
196 void* aModLib = dlopen( aFileName.c_str(), RTLD_LAZY | RTLD_GLOBAL );
198 if(!aModLib && theLibName != "DFBrowser") { // don't show error for internal debugging tool
199 std::string anErrorMsg = "Failed to load " + aFileName;
201 DWORD dwLastError = ::GetLastError();
202 LPSTR messageBuffer = NULL;
203 size_t size = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
204 FORMAT_MESSAGE_FROM_SYSTEM |
205 FORMAT_MESSAGE_IGNORE_INSERTS,
208 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
209 (LPSTR)&messageBuffer, 0, NULL);
210 anErrorMsg += ": " + std::string(messageBuffer, size);
212 anErrorMsg += ": " + std::string(dlerror());
214 std::cerr << anErrorMsg << std::endl;
215 Events_Error::send(anErrorMsg);
219 void Config_ModuleReader::addDependencyModule(const std::string& theModuleName)
221 myDependencyModules.insert(normalize(theModuleName));