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