1 // Copyright (C) 2014-2023 CEA, EDF
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
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>
26 #include <Events_Loop.h>
27 #include <Events_InfoMessage.h>
28 #include <libxml/parser.h>
29 #include <libxml/tree.h>
35 #pragma warning(disable : 4996) // for getenv
43 static const char FSEP = '\\';
45 static const char FSEP = '/';
48 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName, bool isXMLContent)
49 : myXmlDoc(NULL), myRootFileName(theXmlFileName)
51 isFromMemory = isXMLContent;
53 myDocumentPath = findConfigFile(theXmlFileName);
54 if (myDocumentPath.empty()) {
55 Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(theXmlFileName).send();
60 Config_XMLReader::~Config_XMLReader()
66 std::string Config_XMLReader::resourcesConfigFile()
69 char* anEnv = getenv("SHAPER_ROOT_DIR");
71 aValue = std::string(anEnv) +
72 FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
74 anEnv = getenv("CADBUILDER_ROOT_DIR");
76 aValue = std::string(anEnv) + FSEP + "resources";
82 std::string Config_XMLReader::pluginConfigFile()
85 char* anEnv = getenv("SHAPER_ROOT_DIR");
87 aValue = std::string(anEnv) +
88 FSEP + "share" + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
90 anEnv = getenv("CADBUILDER_ROOT_DIR");
92 aValue = std::string(anEnv) + FSEP + "plugins";
99 std::string Config_XMLReader::findConfigFile(const std::string theFileName, const int theFindIndex)
101 int aResultIndex = 0;
102 for(int aSolution = 0; aSolution < 12; aSolution++) {
103 std::string aFileName;
104 if (aSolution == 0) {
105 Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
108 aFileName = aProp->value();
110 std::ostringstream anEnvName;
112 anEnvName<<"SHAPER_ROOT_DIR";
113 else if (aSolution == 2)
114 anEnvName<<"CADBUILDER_ROOT_DIR";
116 anEnvName<<"CADBUILDER_ROOT_DIR";
118 char* anEnv = getenv(anEnvName.str().c_str());
121 if (aSolution > 2) { // there may be several paths separated by ";" symbol
123 std::string anEnvPart = anEnv;
124 size_t aPosStart = 0, aPosEnd;
125 for(int aSubNum = 0; aSubNum < aSolution - 3; aSubNum++) {
127 aPosStart = anEnvPart.find(';', aPosStart);
128 if (aPosStart == std::string::npos)
131 if (aPosStart == std::string::npos)
135 aPosEnd = anEnvPart.find(';', aPosStart);
136 aFileName = anEnvPart.substr(aPosStart,
137 aPosEnd == std::string::npos ? aPosEnd : aPosEnd - aPosStart) + FSEP;
140 aFileName = std::string(anEnv) + FSEP;
143 aFileName += std::string("share") + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
144 else if (aSolution == 2)
145 aFileName += "plugins";
148 aFileName += FSEP + theFileName;
149 std::ifstream aTestFile(aFileName);
151 if (aResultIndex == theFindIndex)
154 if (aSolution == 1) // don't allow SHAPER and CADBuilder paths treated simultaneously
158 return ""; // no files found
161 void Config_XMLReader::readAll()
164 myXmlDoc = xmlParseMemory(myRootFileName.c_str(), (int)myRootFileName.length());
165 xmlNodePtr aRoot = xmlDocGetRootElement(myXmlDoc);
166 readRecursively(aRoot);
170 // to load external modules dependencies (like GEOM for Connector Feature)
171 Config_ModuleReader::loadScript("salome.shaper.initConfig", false);
173 for(int aSolution = 0; true; aSolution++) {
174 std::string aFoundFile = findConfigFile(myRootFileName, aSolution);
175 if (aFoundFile.empty()) {
176 break; // no more solutions
179 if (myXmlDoc != NULL) { // clear the previous XML document - now the new one will be opened
180 xmlFreeDoc(myXmlDoc);
183 xmlNodePtr aRoot = findRoot(aFoundFile);
184 readRecursively(aRoot);
188 void Config_XMLReader::processNode(xmlNodePtr theNode)
190 if (isNode(theNode, NODE_SOURCE, NULL)) {
191 std::string aSourceFile = getProperty(theNode, SOURCE_FILE);
192 Config_XMLReader aSourceReader = Config_XMLReader(aSourceFile);
193 readRecursively(aSourceReader.findRoot());
195 //std::cout << "Config_XMLReader::sourced node: " << aSourceFile << std::endl;
200 void Config_XMLReader::cleanup(xmlNodePtr)
206 bool Config_XMLReader::processChildren(xmlNodePtr /*aNode*/)
212 xmlNodePtr Config_XMLReader::findRoot(const std::string theDocumentPath)
214 std::string aDocPath = theDocumentPath.empty() ? myDocumentPath : theDocumentPath;
215 if (myXmlDoc == NULL) {
216 myXmlDoc = xmlParseFile(aDocPath.c_str());
218 if (myXmlDoc == NULL) {
220 std::cout << "Config_XMLReader::import: " << "Document " << aDocPath
221 << " is not parsed successfully." << std::endl;
225 xmlNodePtr aRoot = xmlDocGetRootElement(myXmlDoc);
228 std::cout << "Config_XMLReader::import: " << "Error: empty document";
234 void Config_XMLReader::readRecursively(xmlNodePtr theParent)
238 xmlNodePtr aNode = theParent->xmlChildrenNode;
239 for (; aNode; aNode = aNode->next) {
240 //Still no text processing in features...
241 if (!isElementNode(aNode)) {
245 if (processChildren(aNode)) {
246 readRecursively(aNode);
253 xmlNodePtr Config_XMLReader::node(void* theNode)
255 return static_cast<xmlNodePtr>(theNode);
259 std::string Config_XMLReader::getNodeName(xmlNodePtr theNode)
261 std::string result = "";
262 char* aPropChars = (char*) theNode->name;
263 if (!aPropChars || aPropChars[0] == 0)
265 result = std::string(aPropChars);
269 void Config_XMLReader::storeAttribute(xmlNodePtr theNode, const char* theAttribute, bool doClean)
271 std::string aKey = getNodeName(theNode) + ":" + std::string(theAttribute);
272 std::string aValue = getProperty(theNode, theAttribute);
273 if (doClean || !aValue.empty()) {
274 myCachedAttributes[aKey] = aValue;
279 std::string Config_XMLReader::restoreAttribute(xmlNodePtr theNode, const char* theAttribute)
281 return restoreAttribute(getNodeName(theNode).c_str(), theAttribute);
285 std::string Config_XMLReader::restoreAttribute(const char* theNodeName, const char* theAttribute)
287 std::string aKey = std::string(theNodeName) + ":" + std::string(theAttribute);
288 std::string result = "";
289 if(myCachedAttributes.find(aKey) != myCachedAttributes.end()) {
290 result = myCachedAttributes[aKey];
295 bool Config_XMLReader::cleanupAttribute(xmlNodePtr theNode, const char* theNodeAttribute)
297 return cleanupAttribute(getNodeName(theNode).c_str(), theNodeAttribute);
300 bool Config_XMLReader::cleanupAttribute(const char* theNodeName, const char* theNodeAttribute)
302 std::string aKey = std::string(theNodeName) + ":" + std::string(theNodeAttribute);
304 std::map<std::string, std::string>::iterator anEntry = myCachedAttributes.find(aKey);
305 if( anEntry != myCachedAttributes.end()) {
306 myCachedAttributes.erase(anEntry);
313 const char* Config_XMLReader::encoding() const
315 return (const char*) myXmlDoc->encoding;