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