Salome HOME
Save foreach state - work in progress.
[modules/yacs.git] / src / runtime / XMLNode.cxx
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 {
57   _implementation=IMPL_NAME;
58   _ref = other._ref;
59 }
60
61 XmlNode::XmlNode(const std::string& name)
62   : ServiceNode(name)
63 {
64   _implementation=IMPL_NAME;
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
93 void XmlNode::execute()
94 {
95   DEBTRACE("execute");
96   char dir[]="yacsXXXXXX";
97   // add a lock around mkdtemp (seems not thread safe)
98   {
99     YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&MUTEX);
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