Salome HOME
Copyright update 2021
[modules/geom.git] / src / GEOMUtils / GEOMUtils_XmlHandler.cxx
1 // Copyright (C) 2013-2021  CEA/DEN, EDF R&D, OPEN CASCADE
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 "GEOMUtils_XmlHandler.hxx"
21 #include <Basics_Utils.hxx>
22
23 #include <libxml/parser.h>
24 #include <algorithm>
25
26 #ifdef WIN32
27 #include <windows.h>
28 #include <algorithm>
29 #else
30 #include <unistd.h>
31 #endif
32
33 //#define MYDEBUG
34
35 namespace
36 {
37   const char*    env_var     = "GEOM_PluginsList";
38
39   const xmlChar* root_tag    = (xmlChar*)"geom-plugins";
40   const xmlChar* plugin_tag  = (xmlChar*)"geom-plugin";
41   const xmlChar* name_tag    = (xmlChar*)"name";
42   const xmlChar* server_tag  = (xmlChar*)"server-lib";
43   const xmlChar* gui_tag     = (xmlChar*)"gui-lib";
44   const xmlChar* actions_tag = (xmlChar*)"actions";
45   const xmlChar* action_tag  = (xmlChar*)"action";
46   const xmlChar* label_tag   = (xmlChar*)"label";
47   const xmlChar* icon_tag    = (xmlChar*)"icon";
48   const xmlChar* menu_tag    = (xmlChar*)"menu";
49   const xmlChar* tooltip_tag = (xmlChar*)"tooltip";
50   const xmlChar* status_tag  = (xmlChar*)"status-bar";
51   const xmlChar* accel_tag   = (xmlChar*)"accel";
52
53   std::string toUpper( const std::string& s )
54   {
55     std::string r = s;
56     std::transform( r.begin(), r.end(), r.begin(), toupper );
57     return r;
58   }
59
60   std::string toLower( const std::string& s )
61   {
62     std::string r = s;
63     std::transform( r.begin(), r.end(), r.begin(), tolower );
64     return r;
65   }
66
67   std::string readXmlAttribute(xmlNodePtr node, const xmlChar* attribute)
68   {
69     std::string result = "";
70     xmlChar* strAttr = xmlGetProp(node, attribute);
71     if (strAttr != NULL) {
72       result = (char*)strAttr;
73       xmlFree(strAttr);
74     }
75     return result;
76   }
77
78   std::list<std::string> getPluginXMLFiles()
79   {
80           std::list<std::string> xmlPaths;
81
82 #ifdef WIN32
83 #ifdef UNICODE
84           std::wstring sep = L"\\";
85 #else
86           std::string sep = "\\";
87 #endif
88 #else
89           std::string sep = "/";
90 #endif
91
92 #if defined(WIN32) && defined(UNICODE)
93           std::wstring wenv_var = Kernel_Utils::utf8_decode_s(env_var);
94           if (const wchar_t* var = _wgetenv(wenv_var.c_str()))
95           {
96                   std::wstring plugins = var;
97 #else
98           if (const char* var = getenv(env_var))
99           {
100                   std::string plugins = var;
101 #endif
102                   std::string::size_type from = 0, pos;
103                   while (from < plugins.size())
104                   {
105 #if defined(WIN32) && defined(UNICODE)
106                           pos = plugins.find(L':', from);
107                           std::wstring plugin;
108 #else
109                           pos = plugins.find(':', from);
110                           std::string plugin;
111 #endif
112                           if (pos != std::string::npos)
113                                   plugin = plugins.substr(from, pos - from);
114                           else
115                                   plugin = plugins.substr(from), pos = plugins.size();
116                           from = pos + 1;
117
118                           if (plugin.size() == 0) continue;
119 #if defined(WIN32) && defined(UNICODE)
120                           std::wstring pluginRoot = plugin + L"_ROOT_DIR";
121                           std::transform(pluginRoot.begin(), pluginRoot.end(), pluginRoot.begin(), ::toupper);
122                           const wchar_t* rootDirGeom = _wgetenv(L"GEOM_ROOT_DIR");
123                           const wchar_t* rootDirPlugin = _wgetenv(pluginRoot.c_str());
124 #else
125                           std::string pluginRoot = toUpper(plugin + "_ROOT_DIR");
126
127                           const char* rootDirGeom = getenv("GEOM_ROOT_DIR");
128                           const char* rootDirPlugin = getenv(pluginRoot.c_str());
129 #endif
130
131                           bool fileOK = false;
132                           if (rootDirGeom) {
133
134 #if defined(WIN32) && defined(UNICODE)
135                                   std::wstring xmlPath = rootDirGeom;
136                                   if (xmlPath[xmlPath.size() - 1] != sep[0])
137                                           xmlPath += sep;
138                                   xmlPath += L"share" + sep + L"salome" + sep + L"resources" + sep + L"geom" + sep + plugin + L".xml";
139 #else
140                                   std::string xmlPath = rootDirGeom;
141                                   if (xmlPath[xmlPath.size() - 1] != sep[0])
142                                           xmlPath += sep;
143                                   xmlPath += "share" + sep + "salome" + sep + "resources" + sep + "geom" + sep + plugin + ".xml";
144 #endif
145
146 #ifdef WIN32
147                                   fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES);
148 #else
149                                   fileOK = (access(xmlPath.c_str(), F_OK) == 0);
150 #endif
151                                   if (fileOK)
152 #if defined(WIN32) && defined(UNICODE)
153                                           xmlPaths.push_back(Kernel_Utils::utf8_encode_s(xmlPath));
154 #else
155                                           xmlPaths.push_back(xmlPath);
156 #endif
157                           }
158                           if (!fileOK && rootDirPlugin) {
159 #if defined(WIN32) && defined(UNICODE)
160                                   std::wstring xmlPath = rootDirPlugin;
161                                   if (xmlPath[xmlPath.size() - 1] != sep[0])
162                                           xmlPath += sep;
163                                   std::transform(plugin.begin(), plugin.end(), plugin.begin(), ::tolower);
164                                   xmlPath += L"share" + sep + L"salome" + sep + L"resources" + sep + plugin + sep + plugin + L".xml";
165
166 #else
167                                   std::string xmlPath = rootDirPlugin;
168                                   if (xmlPath[xmlPath.size() - 1] != sep[0])
169                                           xmlPath += sep;
170                                   xmlPath += "share" + sep + "salome" + sep + "resources" + sep + toLower(plugin) + sep + plugin + ".xml";
171 #endif
172
173 #ifdef WIN32
174                                   fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES);
175 #else
176                                   fileOK = (access(xmlPath.c_str(), F_OK) == 0);
177 #endif
178 #if defined(WIN32) && defined(UNICODE)
179                                   xmlPaths.push_back(Kernel_Utils::utf8_encode_s(xmlPath));
180 #else
181                                   xmlPaths.push_back(xmlPath);
182 #endif
183                           }
184                   }
185           }
186           return xmlPaths;
187   }
188
189 #ifdef MYDEBUG
190   void dumpinfo(const GEOMUtils::PluginInfo& info)
191   {
192     printf("DUMPING PLUGIN INFO\n");
193     GEOMUtils::PluginInfo::const_iterator it;
194     for (it = info.begin(); it != info.end(); ++it) {
195       GEOMUtils::PluginData pdata = *it;
196       printf("Plugin: %s\n", pdata.name.c_str());
197       printf("  serverLib = %s\n", pdata.serverLib.c_str());
198       printf("  clientLib = %s\n", pdata.clientLib.c_str());
199       printf("  actions:\n");
200       std::list<GEOMUtils::ActionData>::const_iterator ait;
201       for (ait = pdata.actions.begin(); ait != pdata.actions.end(); ++ait) {
202         GEOMUtils::ActionData adata = *ait;
203         printf("     label      = %s\n", adata.label.c_str());
204         printf("     icon       = %s\n", adata.icon.c_str());
205         printf("     menuText   = %s\n", adata.menuText.c_str());
206         printf("     toolTip    = %s\n", adata.toolTip.c_str());
207         printf("     statusText = %s\n", adata.statusText.c_str());
208         printf("\n");
209       }
210       printf("-----\n");
211     }
212   }
213 #endif
214 }
215
216 namespace GEOMUtils
217 {
218   PluginInfo ReadPluginInfo()
219   {
220     PluginInfo info;
221
222     std::list<std::string> xmlPaths = getPluginXMLFiles();
223
224     std::list<std::string>::const_iterator fit;
225
226     for ( fit = xmlPaths.begin(); fit != xmlPaths.end(); ++fit )
227     {
228       std::string fileName = *fit;
229
230       int options = XML_PARSE_HUGE | XML_PARSE_NOCDATA;
231       xmlDocPtr doc = xmlReadFile( fileName.c_str(), NULL, options );
232
233       if ( doc )
234       {
235         // get root node
236         xmlNodePtr root = xmlDocGetRootElement(doc);
237
238         // check if it is plugins container node
239         if (xmlStrcmp(root->name, root_tag) == 0)
240         {
241           // iterate through children, to get plugins data
242           for (xmlNodePtr node = root->children; node; node = node->next)
243           {
244             if (xmlStrcmp(node->name, plugin_tag) == 0)
245             {
246               // plugin node
247               PluginData data;
248               data.name      = readXmlAttribute(node, name_tag);
249               data.serverLib = readXmlAttribute(node, server_tag);
250               data.clientLib = readXmlAttribute(node, gui_tag);
251               // iterate through children, to find actions container node
252               for (xmlNodePtr subnode = node->children; subnode; subnode = subnode->next)
253               {
254                 if (xmlStrcmp(subnode->name, actions_tag) == 0)
255                 {
256                   // actions container node
257                   // iterate through children, to get actions data
258                   for (xmlNodePtr subsubnode = subnode->children; subsubnode; subsubnode = subsubnode->next)
259                   {
260                     if (xmlStrcmp(subsubnode->name, action_tag) == 0)
261                     {
262                       // action node
263                       ActionData action;
264                       action.label      = readXmlAttribute(subsubnode, label_tag);
265                       action.icon       = readXmlAttribute(subsubnode, icon_tag);
266                       action.menuText   = readXmlAttribute(subsubnode, menu_tag);
267                       action.toolTip    = readXmlAttribute(subsubnode, tooltip_tag);
268                       action.statusText = readXmlAttribute(subsubnode, status_tag);
269                       action.accel      = readXmlAttribute(subsubnode, accel_tag);
270                       if (action.label != "")
271                         data.actions.push_back(action);
272                     } // end action node
273                   } // end iteration through actions container node children
274                 } // end actions container node
275               } // end iterations through plugin node children
276
277               if (data.name != "")
278                 info.push_back(data);
279             } // end plugin node
280           } // end iterations through plugins container node children
281         } // end root node
282
283         xmlFreeDoc(doc);
284         //xmlCleanupParser();//vsr: xmlCleanupParser should not be called from the application
285       } // end xml doc
286     }
287 #ifdef MYDEBUG
288     dumpinfo(info);
289 #endif
290     return info;
291   }
292 }