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