Version: 9.16.0
XMLNode.cxx
Go to the documentation of this file.
1// Copyright (C) 2006-2026 CEA, EDF
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 "XMLNode.hxx"
21#include "XMLPorts.hxx"
22#include "Mutex.hxx"
23#include "TypeCode.hxx"
24#include "AutoLocker.hxx"
25
26#include <libxml/parser.h>
27#include <libxml/tree.h>
28
29#include <stdlib.h>
30#include <iostream>
31#include <fstream>
32#include <sys/types.h>
33#include <sys/stat.h>
34
35#ifdef WIN32
36#include <windows.h>
37#include <io.h>
38#define chmod _chmod
39#endif
40#ifdef __APPLE__
41#include <unistd.h> // for mkdtemp
42#endif
43
44//#define _DEVDEBUG_
45#include "YacsTrace.hxx"
46
47using namespace YACS::ENGINE;
48using namespace std;
49
50const char XmlNode::IMPL_NAME[]="XML";
51const char XmlNode::KIND[]="xmlsh";
52static YACS::BASES::Mutex MUTEX;
53
54XmlNode::XmlNode(const XmlNode& other, ComposedNode *father)
55 : _script(other._script), ServiceNode(other, father)
56{
58 _ref = other._ref;
59}
60
61XmlNode::XmlNode(const std::string& name)
62 : ServiceNode(name)
63{
65}
66
67Node *XmlNode::simpleClone(ComposedNode *father, bool editionOnly) const
68{
69 return new XmlNode(*this,father);
70}
71
72void XmlNode::setRef(const std::string& ref)
73{
74 //No component instance here
75 _ref=ref;
76}
77
78void XmlNode::setScript(const std::string& script)
79{
80 _script=script;
81}
82
83std::string XmlNode::getScript() const
84{
85 return _script;
86}
87
88std::string XmlNode::getKind() const
89{
90 return KIND;
91}
92
94{
95 DEBTRACE("execute");
96 char dir[]="yacsXXXXXX";
97 // add a lock around mkdtemp (seems not thread safe)
98 {
100#ifdef WIN32
101#ifdef UNICODE
102wchar_t mdir[512 + 1];
103#else
104 char mdir[512 + 1];
105#endif
106 GetTempPath(MAX_PATH+1, mdir);
107 CreateDirectory(mdir, NULL);
108#else
109 char* mdir=mkdtemp(dir);
110#endif
111 if(mdir==NULL)
112 {
113 perror("mkdtemp failed");
114 std::cerr << "Problem in mkdtemp " << dir << " " << mdir << std::endl;
115 throw Exception("Execution problem in mkdtemp");
116 }
117 }
118 std::string sdir(dir);
119 std::string input=sdir+"/input";
120 std::ofstream f(input.c_str());
121 f<<"<methodCall> <methodName>" << _method << "</methodName> <params>"<<std::endl;
122 DEBTRACE("---------------XmlNode::inputs---------------");
123 list<InputPort *>::iterator iter;
124 for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
125 {
126 InputXmlPort *p=(InputXmlPort *)*iter;
127 DEBTRACE("port name: " << p->getName());
128 DEBTRACE("port kind: " << p->edGetType()->kind());
129 const char* ob=p->getXml();
130 DEBTRACE("Xml: " << ob );
131 f<<"<param>" << ob << "</param>"<<std::endl;
132 }
133 f<<"</params>"<<std::endl;
134 f<<"</methodCall>"<<std::endl;
135 f.close();
136 DEBTRACE("--------------XmlNode::calculation---------------" << _ref );
137 std::string call=sdir+"/run.sh";
138 std::ofstream run(call.c_str());
139 run << "#!/bin/sh" << std::endl;
140 run << "cd " << sdir << std::endl;
141 if(_ref[0]=='/' || _ref[0]=='~')
142 run << _ref << "> stdout 2>&1 " << std::endl;
143 else
144 run << "../"<<_ref << "> stdout 2>&1 " << std::endl;
145 //run << "cat stdout" << std::endl;
146 run.close();
147 chmod(call.c_str(),00777);
148
149 std::string call2="/bin/sh "+call;
150 int ret=system(call2.c_str());
151 if(ret)
152 {
153 std::cerr << "Problem: " << ret << std::endl;
154 DEBTRACE("Problem: " << ret);
155 throw Exception("Execution problem");
156 }
157 std::string output=sdir+"/output";
158 xmlDocPtr doc;
159 doc = xmlReadFile(output.c_str(), NULL, 0);
160 if (doc == NULL)
161 {
162 DEBTRACE("Failed to parse " << output);
163 throw Exception("Execution problem");
164 }
165 xmlNodePtr cur;
166 cur = xmlDocGetRootElement(doc);
167 if (cur == NULL)
168 {
169 DEBTRACE("empty document " );
170 xmlFreeDoc(doc);
171 throw Exception("Execution problem");
172 }
173 if (xmlStrcmp(cur->name, (const xmlChar *) "methodResponse"))
174 {
175 DEBTRACE("document of the wrong type, root node != methodResponse");
176 xmlFreeDoc(doc);
177 throw Exception("Execution problem");
178 }
179 cur = cur->xmlChildrenNode;
180 xmlBufferPtr buf=xmlBufferCreate();
181 list<OutputPort *>::iterator iter2;
182 iter2 = _setOfOutputPort.begin();
184 p=(OutputXmlPort *)*iter2;
185 int nres=0;
186
187 while (cur != NULL)
188 {
189 if ((!xmlStrcmp(cur->name, (const xmlChar *)"fault")))
190 {
191 DEBTRACE("exception in shell" );
192 xmlFreeDoc(doc);
193 throw Exception("Execution problem");
194 }
195 if ((!xmlStrcmp(cur->name, (const xmlChar *)"params")))
196 {
197 xmlNodePtr cur0 = cur->xmlChildrenNode;
198 while (cur0 != NULL)
199 {
200 if ((!xmlStrcmp(cur0->name, (const xmlChar *)"param")))
201 {
202 xmlNodePtr cur1 = cur0->xmlChildrenNode;
203 while (cur1 != NULL)
204 {
205 if ((!xmlStrcmp(cur1->name, (const xmlChar *)"value")))
206 {
207 xmlNodePtr cur2=cur1->xmlChildrenNode;
208 while (cur2 != NULL)
209 {
210 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"int")))
211 {
212 //got an int
214 {
215 //mismatch
216 xmlBufferFree(buf);
217 xmlFreeDoc(doc);
218 throw Exception("Execution problem:mismatch in output numbers");
219 }
220 xmlBufferEmpty(buf);
221 xmlNodeDump(buf,doc,cur1,0,0);
222 DEBTRACE(xmlBufferContent(buf));
223 p->put(xmlBufferContent(buf));
224 }
225 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"double")))
226 {
227 //got an double
229 {
230 //mismatch
231 xmlBufferFree(buf);
232 xmlFreeDoc(doc);
233 throw Exception("Execution problem:mismatch in output numbers");
234 }
235 xmlBufferEmpty(buf);
236 xmlNodeDump(buf,doc,cur1,0,0);
237 DEBTRACE(xmlBufferContent(buf));
238 p->put(xmlBufferContent(buf));
239 }
240 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"string")))
241 {
242 //got an string
244 {
245 //mismatch
246 xmlBufferFree(buf);
247 xmlFreeDoc(doc);
248 throw Exception("Execution problem:mismatch in output port numbers");
249 }
250 xmlBufferEmpty(buf);
251 xmlNodeDump(buf,doc,cur1,0,0);
252 DEBTRACE(xmlBufferContent(buf));
253 p->put(xmlBufferContent(buf));
254 }
255 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"boolean")))
256 {
257 //got an boolean
259 {
260 //mismatch
261 xmlBufferFree(buf);
262 xmlFreeDoc(doc);
263 throw Exception("Execution problem:mismatch in output port numbers");
264 }
265 xmlBufferEmpty(buf);
266 xmlNodeDump(buf,doc,cur1,0,0);
267 DEBTRACE(xmlBufferContent(buf));
268 p->put(xmlBufferContent(buf));
269 }
270 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"objref")))
271 {
272 //got an objref
274 {
275 //mismatch
276 xmlBufferFree(buf);
277 xmlFreeDoc(doc);
278 throw Exception("Execution problem:mismatch in output port numbers");
279 }
280 xmlBufferEmpty(buf);
281 xmlNodeDump(buf,doc,cur1,0,0);
282 DEBTRACE(xmlBufferContent(buf));
283 p->put(xmlBufferContent(buf));
284 }
285 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"struct")))
286 {
287 //got an struct
289 {
290 //mismatch
291 xmlBufferFree(buf);
292 xmlFreeDoc(doc);
293 throw Exception("Execution problem:mismatch in output port numbers");
294 }
295 xmlBufferEmpty(buf);
296 xmlNodeDump(buf,doc,cur1,0,0);
297 DEBTRACE(xmlBufferContent(buf));
298 p->put(xmlBufferContent(buf));
299 }
300 if ((!xmlStrcmp(cur2->name, (const xmlChar *)"array")))
301 {
302 //got a tuple of results or only one result (but a list)
304 {
305 //It's a one result list
306 xmlBufferEmpty(buf);
307 xmlNodeDump(buf,doc,cur1,0,0);
308 DEBTRACE(xmlBufferContent(buf));
309 p->put(xmlBufferContent(buf));
310 }
311 else
312 {
313 //It's a list of results
314 xmlNodePtr cur3=cur2->xmlChildrenNode;
315 while (cur3 != NULL)
316 {
317 if ((!xmlStrcmp(cur3->name, (const xmlChar *)"data")))
318 {
319 xmlNodePtr cur4=cur3->xmlChildrenNode;
320 while (cur4 != NULL)
321 {
322 if ((!xmlStrcmp(cur4->name, (const xmlChar *)"value")))
323 {
324 nres++;
325 if(nres > getNumberOfOutputPorts())
326 {
327 //mismatch
328 xmlBufferFree(buf);
329 xmlFreeDoc(doc);
330 throw Exception("Execution problem:mismatch in output port numbers");
331 }
332 xmlBufferEmpty(buf);
333 xmlNodeDump(buf,doc,cur4,0,0);
334 DEBTRACE(xmlBufferContent(buf));
335 p=(OutputXmlPort *)*iter2;
336 p->put(xmlBufferContent(buf));
337 iter2++;
338 }
339 cur4 = cur4->next;
340 } // end while value
341 break;
342 }
343 cur3 = cur3->next;
344 } // end while data
345 }
346 break;
347 }
348 cur2 = cur2->next;
349 } // end while array
350 break;
351 }
352 cur1 = cur1->next;
353 } // end while value
354 }
355 cur0 = cur0->next;
356 }// end while param
357 }
358 cur = cur->next;
359 }
360 xmlBufferFree(buf);
361 xmlFreeDoc(doc);
362}
363
364
static YACS::BASES::Mutex MUTEX
Definition: XMLNode.cxx:52
#define DEBTRACE(msg)
Definition: YacsTrace.hxx:31
Base class for all composed nodes.
std::string getName() const
std::list< InputPort * > _setOfInputPort
std::list< OutputPort * > _setOfOutputPort
Class for XML Input Ports.
Definition: XMLPorts.hxx:38
Base class for all nodes.
Definition: Node.hxx:70
std::string _implementation
Definition: Node.hxx:97
Class for XML Output Ports.
Definition: XMLPorts.hxx:68
Class for calculation node associated with a component service.
Definition: ServiceNode.hxx:35
virtual std::string getScript() const
Definition: XMLNode.cxx:83
Node * simpleClone(ComposedNode *father, bool editionOnly) const
Definition: XMLNode.cxx:67
virtual void execute()
Definition: XMLNode.cxx:93
virtual std::string getKind() const
Return the service node kind.
Definition: XMLNode.cxx:88
virtual void setScript(const std::string &script)
Definition: XMLNode.cxx:78
XmlNode(const XmlNode &other, ComposedNode *father)
Definition: XMLNode.cxx:54
static const char IMPL_NAME[]
Definition: XMLNode.hxx:46
virtual void setRef(const std::string &ref)
Associate a new component instance to this service node.
Definition: XMLNode.cxx:72
static const char KIND[]
Definition: XMLNode.hxx:47
std::string _script
Definition: XMLNode.hxx:49
Proc * p
Definition: driver.cxx:216
static char doc[]
Definition: driver.cxx:63
def ref(target, callback=None)
Definition: CONNECTOR.py:120
void * run(void *obj)
Definition: yacs_clt.cxx:54