Salome HOME
Merge remote-tracking branch 'remotes/origin/HigherLevelObjectsHistory'
[modules/shaper.git] / src / Config / Config_XMLReader.cpp
1 // Copyright (C) 2014-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <Config_XMLReader.h>
21 #include <Config_Keywords.h>
22 #include <Config_Common.h>
23 #include <Config_PropManager.h>
24 #include <Config_ModuleReader.h>
25
26 #include <Events_Loop.h>
27 #include <Events_InfoMessage.h>
28 #include <libxml/parser.h>
29 #include <libxml/tree.h>
30
31 #include <fstream>
32 #include <sstream>
33
34 #ifdef WIN32
35 #pragma warning(disable : 4996) // for getenv
36 #endif
37
38 #ifdef _DEBUG
39 #include <iostream>
40 #endif
41
42 #ifdef WIN32
43     static const char FSEP = '\\';
44 #else
45     static const char FSEP = '/';
46 #endif
47
48 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
49     : myXmlDoc(NULL), myRootFileName(theXmlFileName)
50 {
51   myDocumentPath = findConfigFile(theXmlFileName);
52   if (myDocumentPath.empty()) {
53     Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(theXmlFileName).send();
54   }
55 }
56
57 Config_XMLReader::~Config_XMLReader()
58 {
59   xmlFreeDoc(myXmlDoc);
60 }
61
62 // LCOV_EXCL_START
63 std::string Config_XMLReader::resourcesConfigFile()
64 {
65   std::string aValue;
66   char* anEnv = getenv("SHAPER_ROOT_DIR");
67   if (anEnv) {
68     aValue = std::string(anEnv) +
69       FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
70   } else {
71     anEnv = getenv("OPENPARTS_ROOT_DIR");
72     if (anEnv) {
73       aValue = std::string(anEnv) + FSEP + "resources";
74     }
75   }
76   return aValue;
77 }
78
79 std::string Config_XMLReader::pluginConfigFile()
80 {
81   std::string aValue;
82   char* anEnv = getenv("SHAPER_ROOT_DIR");
83   if (anEnv) {
84     aValue = std::string(anEnv) +
85       FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
86   } else {
87     anEnv = getenv("OPENPARTS_ROOT_DIR");
88     if (anEnv) {
89       aValue = std::string(anEnv) + FSEP + "plugins";
90     }
91   }
92   return aValue;
93 }
94 // LCOV_EXCL_STOP
95
96 std::string Config_XMLReader::findConfigFile(const std::string theFileName, const int theFindIndex)
97 {
98   int aResultIndex = 0;
99   for(int aSolution = 0; aSolution < 12; aSolution++) {
100     std::string aFileName;
101     if (aSolution == 0) {
102       Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
103       if (!aProp)
104         continue;
105       aFileName = aProp->value();
106     } else {
107       std::ostringstream anEnvName;
108       if (aSolution == 1)
109         anEnvName<<"SHAPER_ROOT_DIR";
110       else if (aSolution == 2)
111         anEnvName<<"OPENPARTS_ROOT_DIR";
112       else
113         anEnvName<<"OPENPARTS_PLUGINS_DIR";
114
115       char* anEnv = getenv(anEnvName.str().c_str());
116       if (!anEnv)
117         continue;
118       if (aSolution > 2) { // there may be several paths separated by ";" symbol
119 // LCOV_EXCL_START
120         std::string anEnvPart = anEnv;
121         size_t aPosStart = 0, aPosEnd;
122         for(int aSubNum = 0; aSubNum < aSolution - 3; aSubNum++) {
123           aPosStart++;
124           aPosStart = anEnvPart.find(';', aPosStart);
125           if (aPosStart == std::string::npos)
126             break;
127         }
128         if (aPosStart == std::string::npos)
129           break;
130         if (aPosStart != 0)
131           aPosStart++;
132         aPosEnd = anEnvPart.find(';', aPosStart);
133         aFileName = anEnvPart.substr(aPosStart,
134           aPosEnd == std::string::npos ? aPosEnd : aPosEnd - aPosStart) + FSEP;
135 // LCOV_EXCL_STOP
136       } else {
137         aFileName = std::string(anEnv) + FSEP;
138       }
139       if (aSolution == 1)
140         aFileName += std::string("share") + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
141       else if (aSolution == 2)
142         aFileName += "plugins";
143     }
144
145     aFileName += FSEP + theFileName;
146     std::ifstream aTestFile(aFileName);
147     if (aTestFile) {
148       if (aResultIndex == theFindIndex)
149         return aFileName;
150       aResultIndex++;
151       if (aSolution == 1) // don't allow SHAPER and OpenParts paths treated simultaneously
152         aSolution++;
153     }
154   }
155   return ""; // no files found
156 }
157
158 void Config_XMLReader::readAll()
159 {
160   // to load external modules dependencies (like GEOM for Connector Feature)
161   Config_ModuleReader::loadScript("salome.shaper.initConfig", false);
162
163   for(int aSolution = 0; true; aSolution++) {
164     std::string aFoundFile = findConfigFile(myRootFileName, aSolution);
165     if (aFoundFile.empty()) {
166       break; // no more solutions
167     }
168
169     if (myXmlDoc != NULL) { // clear the previous XML document - now the new one will be opened
170       xmlFreeDoc(myXmlDoc);
171       myXmlDoc = NULL;
172     }
173     xmlNodePtr aRoot = findRoot(aFoundFile);
174     readRecursively(aRoot);
175   }
176 }
177
178 void Config_XMLReader::processNode(xmlNodePtr theNode)
179 {
180   if (isNode(theNode, NODE_SOURCE, NULL)) {
181     std::string aSourceFile = getProperty(theNode, SOURCE_FILE);
182     Config_XMLReader aSourceReader = Config_XMLReader(aSourceFile);
183     readRecursively(aSourceReader.findRoot());
184 #ifdef _DEBUG
185     //std::cout << "Config_XMLReader::sourced node: " << aSourceFile << std::endl;
186 #endif
187   }
188 }
189
190 void Config_XMLReader::cleanup(xmlNodePtr)
191 {
192   // do nothing;
193 }
194
195 // LCOV_EXCL_START
196 bool Config_XMLReader::processChildren(xmlNodePtr aNode)
197 {
198   return true;
199 }
200 // LCOV_EXCL_STOP
201
202 xmlNodePtr Config_XMLReader::findRoot(const std::string theDocumentPath)
203 {
204   std::string aDocPath = theDocumentPath.empty() ? myDocumentPath : theDocumentPath;
205   if (myXmlDoc == NULL) {
206     myXmlDoc = xmlParseFile(aDocPath.c_str());
207   }
208   if (myXmlDoc == NULL) {
209 #ifdef _DEBUG
210     std::cout << "Config_XMLReader::import: " << "Document " << aDocPath
211     << " is not parsed successfully." << std::endl;
212 #endif
213     return NULL;
214   }
215   xmlNodePtr aRoot = xmlDocGetRootElement(myXmlDoc);
216 #ifdef _DEBUG
217   if(aRoot == NULL) {
218     std::cout << "Config_XMLReader::import: " << "Error: empty document";
219   }
220 #endif
221   return aRoot;
222 }
223
224 void Config_XMLReader::readRecursively(xmlNodePtr theParent)
225 {
226   if (!theParent)
227     return;
228   xmlNodePtr aNode = theParent->xmlChildrenNode;
229   for (; aNode; aNode = aNode->next) {
230     //Still no text processing in features...
231     if (!isElementNode(aNode)) {
232       continue;
233     }
234     processNode(aNode);
235     if (processChildren(aNode)) {
236       readRecursively(aNode);
237     }
238     cleanup(aNode);
239   }
240 }
241
242 // LCOV_EXCL_START
243 xmlNodePtr Config_XMLReader::node(void* theNode)
244 {
245   return static_cast<xmlNodePtr>(theNode);
246 }
247 // LCOV_EXCL_STOP
248
249 std::string Config_XMLReader::getNodeName(xmlNodePtr theNode)
250 {
251   std::string result = "";
252   char* aPropChars = (char*) theNode->name;
253   if (!aPropChars || aPropChars[0] == 0)
254     return result;
255   result = std::string(aPropChars);
256   return result;
257 }
258
259 void Config_XMLReader::storeAttribute(xmlNodePtr theNode, const char* theAttribute, bool doClean)
260 {
261   std::string aKey = getNodeName(theNode) + ":" + std::string(theAttribute);
262   std::string aValue = getProperty(theNode, theAttribute);
263   if (doClean || !aValue.empty()) {
264     myCachedAttributes[aKey] = aValue;
265   }
266 }
267
268 // LCOV_EXCL_START
269 std::string Config_XMLReader::restoreAttribute(xmlNodePtr theNode, const char* theAttribute)
270 {
271   return restoreAttribute(getNodeName(theNode).c_str(), theAttribute);
272 }
273 // LCOV_EXCL_STOP
274
275 std::string Config_XMLReader::restoreAttribute(const char* theNodeName, const char* theAttribute)
276 {
277   std::string aKey = std::string(theNodeName) + ":" + std::string(theAttribute);
278   std::string result = "";
279   if(myCachedAttributes.find(aKey) != myCachedAttributes.end()) {
280     result = myCachedAttributes[aKey];
281   }
282   return result;
283 }
284
285 bool Config_XMLReader::cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute)
286 {
287   return cleanupAttribute(getNodeName(theNode).c_str(), theNodeAttribute);
288 }
289
290 bool Config_XMLReader::cleanupAttribute(const char* theNodeName, const char* theNodeAttribute)
291 {
292   std::string aKey = std::string(theNodeName) + ":" + std::string(theNodeAttribute);
293   bool result = false;
294   std::map<std::string, std::string>::iterator anEntry = myCachedAttributes.find(aKey);
295   if( anEntry != myCachedAttributes.end()) {
296     myCachedAttributes.erase(anEntry);
297     result = true;
298   }
299   return result;
300 }
301
302 // LCOV_EXCL_START
303 const char* Config_XMLReader::encoding() const
304 {
305   return (const char*) myXmlDoc->encoding;
306 }
307 // LCOV_EXCL_STOP