]> SALOME platform Git repositories - modules/shaper.git/blob - src/Config/Config_ModuleReader.cpp
Salome HOME
0b0245c5ad926af7399c7785dd04ed6f654bd65d
[modules/shaper.git] / src / Config / Config_ModuleReader.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 /*
4  * Config_ModuleReader.cpp
5  *
6  *  Created on: Mar 20, 2014
7  *      Author: sbh
8  */
9
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>
15
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
18
19 // Have to be included before std headers
20 #include <Python.h>
21
22 //Necessary for cerr
23 #include <iostream>
24 #include <algorithm>
25
26 #ifdef WIN32
27 #include <windows.h>
28 #pragma warning(disable : 4996) // for getenv
29 #else
30 #include <dlfcn.h>
31 #endif
32
33 std::map<std::string, Config_ModuleReader::PluginType> Config_ModuleReader::myPluginTypes;
34 std::set<std::string> Config_ModuleReader::myDependencyModules;
35
36 Config_ModuleReader::Config_ModuleReader(const char* theEventGenerated)
37     : Config_XMLReader(PLUGIN_FILE),
38       myEventGenerated(theEventGenerated)
39 {
40 }
41
42 Config_ModuleReader::~Config_ModuleReader()
43 {
44 }
45
46 const std::map<std::string, std::string>& Config_ModuleReader::featuresInFiles() const
47 {
48   return myFeaturesInFiles;
49 }
50
51 /*
52  * Get module name from plugins.xml
53  * (property "module")
54  */
55 std::string Config_ModuleReader::getModuleName()
56 {
57   xmlNodePtr aRoot = findRoot();
58   return getProperty(aRoot, PLUGINS_MODULE);
59 }
60
61 /*
62  *
63  */
64 void Config_ModuleReader::processNode(xmlNodePtr theNode)
65 {
66   if (isNode(theNode, NODE_PLUGIN, NULL)) {
67     if (!hasRequiredModules(theNode))
68       return;
69     std::string aPluginConf = getProperty(theNode, PLUGIN_CONFIG);
70     std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY);
71     std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT);
72     std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf);
73
74     std::list<std::string> aFeatures = importPlugin(aPluginName, aPluginConf);
75     std::list<std::string>::iterator it = aFeatures.begin();
76     for (; it != aFeatures.end(); it++) {
77       myFeaturesInFiles[*it] = aPluginConf;
78     }
79   }
80 }
81
82 bool Config_ModuleReader::processChildren(xmlNodePtr theNode)
83 {
84   return isNode(theNode, NODE_PLUGINS, NULL);
85 }
86
87 bool Config_ModuleReader::hasRequiredModules(xmlNodePtr theNode) const
88 {
89   std::string aRequiredModule = normalize(getProperty(theNode, PLUGIN_DEPENDENCY));
90   if(aRequiredModule.empty())
91     return true;
92   std::set<std::string>::iterator it = myDependencyModules.begin();
93   for ( ; it != myDependencyModules.end(); it++ ) {
94     if (*it == aRequiredModule) return true;
95   }
96   return false;
97 }
98
99 std::list<std::string> Config_ModuleReader::importPlugin(const std::string& thePluginLibrary,
100                                                          const std::string& thePluginXmlConf)
101 {
102   if (thePluginXmlConf.empty()) {  //probably a third party library
103     loadLibrary(thePluginLibrary);
104     return std::list<std::string>();
105   }
106
107   Config_FeatureReader aReader = Config_FeatureReader(thePluginXmlConf,
108                                                       thePluginLibrary,
109                                                       myEventGenerated);
110   aReader.readAll();
111   return aReader.features();
112 }
113
114 std::string Config_ModuleReader::addPlugin(const std::string& aPluginLibrary,
115                                            const std::string& aPluginScript,
116                                            const std::string& aPluginConf)
117 {
118   PluginType aType = Config_ModuleReader::Binary;
119   std::string aPluginName;
120   if (!aPluginLibrary.empty()) {
121     aPluginName = aPluginLibrary;
122     if (aPluginConf.empty()) {
123       aType = Config_ModuleReader::Intrenal;
124     }
125   } else if (!aPluginScript.empty()) {
126     aPluginName = aPluginScript;
127     aType = Config_ModuleReader::Python;
128   }
129   if(!aPluginName.empty()) {
130     myPluginTypes[aPluginName] = aType;
131   }
132   addDependencyModule(aPluginName);
133   return aPluginName;
134 }
135
136 void Config_ModuleReader::loadPlugin(const std::string& thePluginName)
137 {
138   PluginType aType = Config_ModuleReader::Binary;
139   if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) {
140     aType = myPluginTypes.at(thePluginName);
141   }
142   switch (aType) {
143     case Config_ModuleReader::Python:
144       loadScript(thePluginName);
145       break;
146     case Config_ModuleReader::Binary:
147     case Config_ModuleReader::Intrenal:
148     default:
149       loadLibrary(thePluginName);
150       break;
151   }
152 }
153
154 void Config_ModuleReader::loadScript(const std::string& theFileName)
155 {
156   /* aquire python thread */
157   PyGILState_STATE gstate = PyGILState_Ensure();
158
159   PyObject* module = PyImport_ImportModule(theFileName.c_str());
160   if (!module) {
161     std::string anErrorMsg = "An error occured while importing " + theFileName;
162     //Get detailed error message:
163     if (PyErr_Occurred()) {
164       PyObject *pstr, *ptype, *pvalue, *ptraceback;
165       PyErr_Fetch(&ptype, &pvalue, &ptraceback);
166       PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
167       pstr = PyObject_Str(pvalue);
168       std::string aPyError = std::string(PyString_AsString(pstr));
169       if (!aPyError.empty()) {
170         anErrorMsg += ":\n" + aPyError;
171       }
172       Py_XDECREF(pstr);
173       Py_XDECREF(ptype);
174       Py_XDECREF(pvalue);
175       Py_XDECREF(ptraceback);
176     }
177     Events_Error::send(anErrorMsg);
178   }
179
180   /* release python thread */
181   PyGILState_Release(gstate);
182 }
183
184 void Config_ModuleReader::loadLibrary(const std::string& theLibName)
185 {
186   std::string aFileName = library(theLibName);
187   if (aFileName.empty())
188     return;
189
190 #ifdef WIN32
191   HINSTANCE aModLib = ::LoadLibrary(aFileName.c_str());
192 #else
193   void* aModLib = dlopen( aFileName.c_str(), RTLD_LAZY | RTLD_GLOBAL );
194 #endif
195   if(!aModLib && theLibName != "DFBrowser") { // don't show error for internal debugging tool
196     std::string anErrorMsg = "Failed to load " + aFileName;
197     #ifndef WIN32
198     anErrorMsg += ": " + std::string(dlerror());
199     #endif
200     Events_Error::send(anErrorMsg);
201   }
202 }
203
204 void Config_ModuleReader::addDependencyModule(const std::string& theModuleName)
205 {
206   myDependencyModules.insert(normalize(theModuleName));
207 }
208