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