Salome HOME
Merge branch 'Dev_0.6.1' of newgeom:newgeom into Dev_0.6.1
[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
25 #ifdef WIN32
26 #include <windows.h>
27 #else
28 #include <dlfcn.h>
29 #endif
30
31 std::map<std::string, Config_ModuleReader::PluginType> Config_ModuleReader::myPluginTypes;
32
33 Config_ModuleReader::Config_ModuleReader(const char* theEventGenerated)
34     : Config_XMLReader(PLUGIN_FILE),
35       myEventGenerated(theEventGenerated)
36 {
37 }
38
39 Config_ModuleReader::~Config_ModuleReader()
40 {
41 }
42
43 const std::map<std::string, std::string>& Config_ModuleReader::featuresInFiles() const
44 {
45   return myFeaturesInFiles;
46 }
47
48 /*
49  * Get module name from plugins.xml
50  * (property "module")
51  */
52 std::string Config_ModuleReader::getModuleName()
53 {
54   xmlNodePtr aRoot = findRoot();
55   return getProperty(aRoot, PLUGINS_MODULE);
56 }
57
58 /*
59  *
60  */
61 void Config_ModuleReader::processNode(xmlNodePtr theNode)
62 {
63   if (isNode(theNode, NODE_PLUGIN, NULL)) {
64     std::string aPluginConf = getProperty(theNode, PLUGIN_CONFIG);
65     std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY);
66     std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT);
67     std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf);
68
69     std::list<std::string> aFeatures = importPlugin(aPluginName, aPluginConf);
70     std::list<std::string>::iterator it = aFeatures.begin();
71     for (; it != aFeatures.end(); it++) {
72       myFeaturesInFiles[*it] = aPluginConf;
73     }
74   }
75 }
76
77 bool Config_ModuleReader::processChildren(xmlNodePtr theNode)
78 {
79   return isNode(theNode, NODE_PLUGINS, NULL);
80 }
81
82 std::list<std::string> Config_ModuleReader::importPlugin(const std::string& thePluginLibrary,
83                                                          const std::string& thePluginXmlConf)
84 {
85   if (thePluginXmlConf.empty()) {  //probably a third party library
86     loadLibrary(thePluginLibrary);
87     return std::list<std::string>();
88   }
89
90   Config_FeatureReader aReader = Config_FeatureReader(thePluginXmlConf,
91                                                       thePluginLibrary,
92                                                       myEventGenerated);
93   aReader.readAll();
94   return aReader.features();
95 }
96
97 std::string Config_ModuleReader::addPlugin(const std::string& aPluginLibrary,
98                                            const std::string& aPluginScript,
99                                            const std::string& aPluginConf)
100 {
101   PluginType aType = Config_ModuleReader::Binary;
102   std::string aPluginName;
103   if (!aPluginLibrary.empty()) {
104     aPluginName = aPluginLibrary;
105     if (aPluginConf.empty()) {
106       aType = Config_ModuleReader::Intrenal;
107     }
108   } else if (!aPluginScript.empty()) {
109     aPluginName = aPluginScript;
110     aType = Config_ModuleReader::Python;
111   }
112   if(!aPluginName.empty()) {
113     myPluginTypes[aPluginName] = aType;
114
115   }
116   return aPluginName;
117 }
118
119 void Config_ModuleReader::loadPlugin(const std::string thePluginName)
120 {
121   PluginType aType = Config_ModuleReader::Binary;
122   if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) {
123     aType = myPluginTypes.at(thePluginName);
124   }
125   switch (aType) {
126     case Config_ModuleReader::Python:
127       loadScript(thePluginName);
128       break;
129     case Config_ModuleReader::Binary:
130     case Config_ModuleReader::Intrenal:
131     default:
132       loadLibrary(thePluginName);
133       break;
134   }
135 }
136
137 void Config_ModuleReader::loadScript(const std::string theFileName)
138 {
139   /* aquire python thread */
140   PyGILState_STATE gstate = PyGILState_Ensure();
141   PyObject* module = PyImport_ImportModule(theFileName.c_str());
142
143   if (!module) {
144     std::string anErrorMsg = "An error occured while importing " + theFileName;
145     //Get detailed error message:
146     if (PyErr_Occurred()) {
147       PyObject *ptype, *pvalue, *ptraceback;
148       PyErr_Fetch(&ptype, &pvalue, &ptraceback);
149       std::string aPyError = std::string(PyString_AsString(pvalue));
150       if (!aPyError.empty()) {
151         anErrorMsg += ":\n" + aPyError;
152       }
153       Py_XDECREF(ptype);
154       Py_XDECREF(pvalue);
155       Py_XDECREF(ptraceback);
156     }
157     Events_Error::send(anErrorMsg);
158   }
159
160   /* release python thread */
161   PyGILState_Release(gstate);
162 }
163
164 void Config_ModuleReader::loadLibrary(const std::string theLibName)
165 {
166   std::string aFileName = library(theLibName);
167   if (aFileName.empty())
168     return;
169
170 #ifdef WIN32
171   HINSTANCE aModLib = ::LoadLibrary(aFileName.c_str());
172 #else
173   void* aModLib = dlopen( aFileName.c_str(), RTLD_LAZY | RTLD_GLOBAL );
174 #endif
175   if(!aModLib && theLibName != "DFBrowser") { // don't show error for internal debugging tool
176     std::string anErrorMsg = "Failed to load " + aFileName;
177     #ifndef WIN32
178     anErrorMsg += ": " + std::string(dlerror());
179     #endif
180     Events_Error::send(anErrorMsg);
181   }
182 }
183