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