Salome HOME
Update copyrights 2014.
[modules/yacs.git] / src / runtime / CORBANode.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 //#define REFCNT
21 //
22 #ifdef REFCNT
23 #define private public
24 #define protected public
25 #include <omniORB4/CORBA.h>
26 #include <omniORB4/internal/typecode.h>
27 #endif
28
29 #include "RuntimeSALOME.hxx"
30 #include "CORBANode.hxx"
31 #include "CORBAComponent.hxx"
32 #include "SalomeComponent.hxx"
33 #include "CORBAPorts.hxx"
34 #include "OutputDataStreamPort.hxx"
35 #include "CalStreamPort.hxx"
36 #include "InPort.hxx"
37 #include "TypeCode.hxx"
38
39 #ifdef SALOME_KERNEL
40 #include "SALOME_NamingService.hxx"
41 #include "SALOME_LifeCycleCORBA.hxx"
42 #include "SALOME_Exception.hh"
43 #endif
44
45 #include <omniORB4/CORBA.h>
46 #include <omniORB4/minorCode.h>
47 #include <iostream>
48 #include <set>
49 #include <list>
50
51 //#define _DEVDEBUG_
52 #include "YacsTrace.hxx"
53
54 using namespace YACS::ENGINE;
55 using namespace std;
56
57 const char CORBANode::IMPL_NAME[]="CORBA";
58 const char CORBANode::KIND[]="CORBA";
59
60 std::string CORBANode::getKind() const
61 {
62   return KIND;
63 }
64
65 //! CORBANode constructor
66 CORBANode::CORBANode(const std::string& name): ServiceNode(name)
67 {
68   _implementation=IMPL_NAME;
69 }
70
71 CORBANode::CORBANode(const CORBANode& other,ComposedNode *father):ServiceNode(other,father)
72 {
73   _implementation=IMPL_NAME;
74 }
75
76 //! Execute the service on the component associated to the node
77 void CORBANode::execute()
78 {
79   YACSTRACE(1, "+++++++++++++ CorbaNode::execute: " << getName() << " +++++++++++++++" );
80   {
81     //DII request building :
82     // a service gets all its in parameters first
83     // then all its out parameters
84     // no inout parameters
85     // the return value (if any) is the first out parameter
86     // not yet user exception (only CORBA exception)
87
88     CORBA::Object_var objComponent=((CORBAComponent*)_component)->getCompoPtr();
89     CORBA::Request_var req = objComponent->_request(_method.c_str());
90     CORBA::NVList_ptr arguments = req->arguments() ;
91
92     DEBTRACE( "+++++++++++++++++CorbaNode::inputs+++++++++++++++++" )
93     int in_param=0;
94     //in parameters
95     list<InputPort *>::iterator iter2;
96     for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
97       {
98         InputCorbaPort *p=(InputCorbaPort *)*iter2;
99         DEBTRACE( "port name: " << p->getName() )
100         DEBTRACE( "port kind: " << p->edGetType()->kind() )
101         CORBA::Any* ob=p->getAny();
102 #ifdef _DEVDEBUG_
103         CORBA::TypeCode_var typcod= ob->type();
104         switch(p->edGetType()->kind())
105           {
106           case Double:
107             CORBA::Double d;
108             *ob >>= d;
109             DEBTRACE( d )
110             break;
111           case Int:
112             CORBA::Long l;
113             *ob >>= l;
114             DEBTRACE( l )
115             break;
116           case String:
117             const char *s;
118             *ob >>= s;
119             DEBTRACE( s )
120             break;
121           case Bool:
122             CORBA::Boolean b;
123             if(*ob >>= CORBA::Any::to_boolean(b))
124               DEBTRACE( b )
125             else 
126               DEBTRACE( "not a boolean" )
127             break;
128           case Objref:
129             DEBTRACE( typcod->id() )
130             break;
131           default:
132             break;
133           }
134 #endif
135         //add_value makes a copy of any (*ob). This copy will be deleted with the request
136         arguments->add_value( p->getName().c_str() , *ob , CORBA::ARG_IN ) ;
137         in_param=in_param+1;
138       }
139     
140     //output parameters
141     DEBTRACE( "+++++++++++++++++CorbaNode::outputs+++++++++++++++++" )
142     list<OutputPort *>::iterator iter;
143     for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
144       {
145         OutputCorbaPort *p=(OutputCorbaPort *)*iter;
146         DEBTRACE( "port name: " << p->getName() )
147         DEBTRACE( "port kind: " << p->edGetType()->kind() )
148         CORBA::Any* ob=p->getAnyOut();
149 #ifdef REFCNT
150         DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)ob->pd_tc.in())->pd_ref_count);
151 #endif
152         //add_value makes a copy of any. Copy will be deleted with request
153         arguments->add_value( p->getName().c_str() , *ob , CORBA::ARG_OUT );
154 #ifdef REFCNT
155         DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)ob->pd_tc.in())->pd_ref_count);
156 #endif
157         delete ob;
158       }
159
160     //return value
161     req->set_return_type(CORBA::_tc_void);
162     
163     DEBTRACE( "+++++++++++++++++CorbaNode::calculation+++++++++++++++++" << _method )
164     req->invoke();
165     CORBA::Exception *exc =req->env()->exception();
166     if( exc )
167       {
168         DEBTRACE( "An exception was thrown!" )
169         DEBTRACE( "The raised exception is of Type:" << exc->_name() )
170
171         std::cerr << "The raised exception is of Type:" << exc->_name() << std::endl;
172         /*
173         if(strcmp(exc->_name(),"MARSHAL") == 0)
174           {
175             const char* ms = ((CORBA::MARSHAL*)exc)->NP_minorString();
176             if (ms)
177                std::cerr << "(CORBA::MARSHAL: minor = " << ms << ")" << std::endl;
178             else
179                std::cerr << "(CORBA::MARSHAL: minor = " << ((CORBA::MARSHAL*)exc)->minor() << ")" << std::endl;
180           }
181           */
182         _errorDetails="Execution problem: the raised exception is of Type:";
183         _errorDetails += exc->_name();
184         throw Exception("Execution problem");
185       }
186     
187     DEBTRACE( "++++++++++++CorbaNode::outputs++++++++++++" )
188     int out_param=in_param;
189     for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
190       {
191         OutputCorbaPort *p=(OutputCorbaPort *)*iter;
192         DEBTRACE( "port name: " << p->getName() )
193         DEBTRACE( "port kind: " << p->edGetType()->kind() )
194         DEBTRACE( "port number: " << out_param )
195         CORBA::Any *ob=arguments->item(out_param)->value();
196 #ifdef REFCNT
197         DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)ob->pd_tc.in())->pd_ref_count);
198 #endif
199 #ifdef _DEVDEBUG_
200         CORBA::TypeCode_var tc=ob->type();
201         switch(p->edGetType()->kind())
202           {
203           case Double:
204             CORBA::Double d;
205             *ob >>= d;
206             DEBTRACE( d )
207             break;
208           case Int:
209             CORBA::Long l;
210             *ob >>= l;
211             DEBTRACE( l )
212             break;
213           case String:
214             const char *s;
215             *ob >>= s;
216             DEBTRACE( s )
217             break;
218           case Objref:
219             DEBTRACE( tc->id() )
220             break;
221           default:
222             break;
223           }
224 #endif
225         //OutputPort must copy the input Any(ob). 
226         //This Any will be deleted with the request.
227         //Copy is made by the method put.
228         p->put(ob);
229         out_param=out_param+1;
230 #ifdef REFCNT
231         DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)ob->pd_tc.in())->pd_ref_count);
232 #endif
233       }
234     DEBTRACE( "++++++++++++++++++++++++++++++++++++++++++" )
235   }
236   //Request has been deleted (_var )
237   //All anys given to the request are deleted : don't forget to copy them 
238   //if you want to keep them
239 #ifdef REFCNT
240   list<OutputPort *>::const_iterator iter;
241   for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
242     {
243       OutputCorbaPort *p=(OutputCorbaPort *)*iter;
244       CORBA::Any *ob=p->getAny();
245       DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)ob->pd_tc.in())->pd_ref_count);
246     }
247 #endif
248   DEBTRACE( "+++++++++++++++++ End CorbaNode::execute: " << getName() << " +++++++++++++++++" )
249 }
250
251 //! Clone the node : must also clone the component instance ?
252 Node *CORBANode::simpleClone(ComposedNode *father, bool editionOnly) const
253 {
254   return new CORBANode(*this,father);
255 }
256
257 //! Create a CORBANode with the same component object and no input or output port
258 /*!
259  *   \param name : node name
260  *   \return       a new CORBANode node
261  */
262 ServiceNode* CORBANode::createNode(const std::string& name)
263 {
264
265   CORBANode* node=  new CORBANode(name);
266   node->setComponent(_component);
267   return node;
268 }
269
270 // SalomeNode Class
271
272 const char SalomeNode::KIND[]="Salome";
273
274 std::string SalomeNode::getKind() const
275 {
276   return KIND;
277 }
278
279 //! SalomeNode constructor
280 SalomeNode::SalomeNode(const std::string& name):ServiceNode(name)
281 {
282   _implementation=CORBANode::IMPL_NAME;
283 }
284
285 SalomeNode::SalomeNode(const SalomeNode& other,ComposedNode *father):ServiceNode(other,father)
286 {
287   _implementation=CORBANode::IMPL_NAME;
288 }
289
290 SalomeNode::~SalomeNode()
291 {
292 }
293
294 #ifdef DSC_PORTS
295 //! Init the datastream ports of the component associated to the node
296 void SalomeNode::initService()
297 {
298   DEBTRACE( "SalomeNode::initService: "<<getName())
299   if(_setOfInputDataStreamPort.size() == 0 && _setOfOutputDataStreamPort.size() == 0)return;
300
301   CORBA::Object_var objComponent=((SalomeComponent*)_component)->getCompoPtr();
302   Engines::Superv_Component_var compo=Engines::Superv_Component::_narrow(objComponent);
303   if( CORBA::is_nil(compo) )
304     {
305       std::string msg="Can't get reference to DSC object (or it was nil).";
306       _errorDetails=msg;
307       throw Exception(msg);
308     }
309   try
310     {
311       if (!_multi_port_node)
312       {
313         CORBA::Boolean ret=compo->init_service(_method.c_str());
314         if(!ret)
315           {
316             _errorDetails="Problem with component '"+_ref+"' in init_service of service '"+ _method + "'";
317             throw Exception(_errorDetails);
318           }
319         //Should check that component port types are the same as those declared in the xml file
320       }
321       else
322       {
323         CORBA::Boolean ret=compo->init_service_with_multiple(_method.c_str(), _param);
324         if(!ret)
325           {
326             _errorDetails="Problem with component '"+_ref+"' in init_service_with_multiple of service '"+ _method + "'";
327             throw Exception(_errorDetails);
328           }
329       }
330     }
331   catch(...)
332     {
333       _errorDetails="Problem with component '"+_ref+"' in init_service of service '"+ _method + "'";
334       throw;
335     }
336 }
337
338 void
339 SalomeNode::addDatastreamPortToInitMultiService(const std::string & port_name, int number)
340 {
341   int index = _param.length();
342   _param.length(index + 1);
343   _param[index].name = CORBA::string_dup(port_name.c_str());
344   _param[index].number = number;
345 }
346
347 //! Connect the datastream ports of the component associated to the node
348 void SalomeNode::connectService()
349 {
350   DEBTRACE( "SalomeNode::connectService: "<<getName());
351   if(_setOfOutputDataStreamPort.size() == 0)return;
352
353   CORBA::Object_var objComponent=((SalomeComponent*)_component)->getCompoPtr();
354   SALOME_NamingService NS(getSALOMERuntime()->getOrb()) ;
355   SALOME_LifeCycleCORBA LCC(&NS) ;
356   CORBA::Object_var obj = NS.Resolve("/ConnectionManager");
357   Engines::ConnectionManager_var manager=Engines::ConnectionManager::_narrow(obj);
358   Engines::Superv_Component_var me=Engines::Superv_Component::_narrow(objComponent);
359   if( CORBA::is_nil(me) )
360     {
361       std::string msg="Can't get reference to Engines::Superv_Component: "+getName();
362       _errorDetails=msg;
363       throw Exception(msg);
364     }
365   std::list<OutputDataStreamPort *>::iterator iter;
366   Engines::ConnectionManager::connectionId id;
367   for(iter = _setOfOutputDataStreamPort.begin(); iter != _setOfOutputDataStreamPort.end(); iter++)
368     {
369       OutputDataStreamPort *port=(OutputDataStreamPort *)*iter;
370       std::set<InPort *> ports=port->edSetInPort();
371       std::set<InPort *>::iterator iterout;
372       for(iterout=ports.begin();iterout != ports.end(); iterout++)
373         {
374           //It's only possible to connect 2 SalomeNode : try to get a SalomeNode
375           SalomeNode* snode= dynamic_cast<SalomeNode*>((*iterout)->getNode());
376           if(snode == 0) //don't connect, it's not a SalomeNode
377             {
378               std::string msg="Can't connect : not a SalomeNode";
379               _errorDetails=msg;
380               throw Exception(msg);
381             }
382
383           CORBA::Object_var comp=((SalomeComponent*)snode->getComponent())->getCompoPtr();
384           if( CORBA::is_nil(comp))
385             {
386               std::string msg="Problem in connectService: " + snode->getName();
387               msg=msg+" Component is probably not launched. Modify your YACS file";
388               _errorDetails=msg;
389               throw Exception(msg);
390             }
391
392           Engines::Superv_Component_var other=Engines::Superv_Component::_narrow(comp);
393           if( CORBA::is_nil(other))
394             {
395               std::string msg="Can't connect to nil Engines::Superv_Component: " + snode->getName();
396               _errorDetails=msg;
397               throw Exception(msg);
398             }
399           try
400             {
401               id=manager->connect(me,port->getName().c_str(),other,(*iterout)->getName().c_str());
402             }
403           catch(Engines::DSC::PortNotDefined& ex)
404             {
405               std::string msg="Problem in connectService. Unknown port: "+port->getName()+" or "+(*iterout)->getName();
406               _errorDetails=msg;
407               throw Exception(msg);
408             }
409           catch(Engines::DSC::BadPortType& ex)
410             {
411               std::string msg="Problem in connectService. Type of provides port is bad. Expected: ";
412               msg=msg + ex.expected.in();
413               msg=msg + "Received: "+ex.received.in();
414               _errorDetails=msg;
415               throw Exception(msg);
416             }
417           catch(Engines::DSC::NilPort& ex)
418             {
419               std::string msg="Problem in connectService. Port is nil: "+port->getName()+" or "+(*iterout)->getName();
420               _errorDetails=msg;
421               throw Exception(msg);
422             }
423           catch( const SALOME::SALOME_Exception& ex )
424             {
425               std::string msg="Problem in connectService. ";
426               msg += ex.details.text.in();
427               msg=msg+getName()+" " + port->getName() + " " + snode->getName() + " " + (*iterout)->getName();
428               _errorDetails=msg;
429               throw Exception(msg);
430             }
431           catch(CORBA::SystemException& ex)
432             {
433               DEBTRACE( "minor code: " << ex.minor() );
434               DEBTRACE( "completion code: " << ex.completed() );
435               std::string msg="Problem in connectService. CORBA System exception ";
436               std::string excname=ex._name();
437               msg=msg+excname + " " +getName()+" " + port->getName() + " " + snode->getName() + " " + (*iterout)->getName();
438               _errorDetails=msg;
439               throw Exception(msg);
440             }
441           catch(...)
442             {
443               std::string msg="Problem in connectService. Unknown exception";
444               msg=msg+getName()+" " + port->getName() + " " + snode->getName() + " " + (*iterout)->getName();
445               _errorDetails=msg;
446               throw Exception(msg);
447             }
448           DEBTRACE("Connected: " <<id<<" "<<getName()<<" "<<port->getName()<<" "<<snode->getName()<<" "<<(*iterout)->getName());
449           ids.push_back(id);
450         }
451     }
452
453   //Init component port properties
454   for(iter = _setOfOutputDataStreamPort.begin(); iter != _setOfOutputDataStreamPort.end(); iter++)
455     {
456       (*iter)->initPortProperties();
457     }
458   std::list<InputDataStreamPort *>::iterator iterin;
459   for(iterin = _setOfInputDataStreamPort.begin(); iterin != _setOfInputDataStreamPort.end(); iterin++)
460     {
461       (*iterin)->initPortProperties();
462     }
463 }
464
465 //! Disconnect the datastream ports of the component associated to the node
466 void SalomeNode::disconnectService()
467 {
468   DEBTRACE( "SalomeNode::disconnectService: "<<getName());
469   // in some rare cases, disconnectService can be called from 2 different threads
470   YACS::BASES::Lock lock(&_mutex);
471
472   if(ids.size() == 0)
473     return;
474
475   SALOME_NamingService NS(getSALOMERuntime()->getOrb()) ;
476   SALOME_LifeCycleCORBA LCC(&NS) ;
477   CORBA::Object_var obj = NS.Resolve("/ConnectionManager");
478   Engines::ConnectionManager_var manager=Engines::ConnectionManager::_narrow(obj);
479   std::list<Engines::ConnectionManager::connectionId>::iterator iter;
480   for(iter = ids.begin(); iter != ids.end(); iter++)
481     {
482       DEBTRACE("Trying to disconnect: " << *iter );
483       try
484         {
485           manager->disconnect(*iter,Engines::DSC::RemovingConnection);
486         }
487       catch(Engines::ConnectionManager::BadId& ex)
488         {
489           DEBTRACE( "Problem in disconnect: " << *iter );
490         }
491       catch(Engines::DSC::PortNotDefined& ex)
492         {
493           DEBTRACE( "Problem in disconnect: " << *iter );
494         }
495       catch(Engines::DSC::PortNotConnected& ex)
496         {
497           DEBTRACE( "Problem in disconnect: " << *iter );
498         }
499       catch(Engines::DSC::BadPortReference& ex)
500         {
501           DEBTRACE( "Problem in disconnect (Engines::DSC::BadPortReference): " << *iter );
502         }
503       catch(CORBA::SystemException& ex)
504         {
505           DEBTRACE( "Problem in disconnect (CORBA::SystemException): " << *iter );
506         }
507       catch(...)
508         {
509           DEBTRACE( "Problem in disconnect: " << *iter );
510         }
511     }
512   ids.clear();
513 }
514
515 void SalomeNode::cleanNodes()
516 {
517   disconnectService();
518 }
519
520 #endif
521
522 //! Execute the service on the component associated to the node
523 void SalomeNode::execute()
524 {
525   YACSTRACE(1,"+++++++++++++++++ SalomeNode::execute: " << getName() << " " << _method << " +++++++++++++++++" );
526   {
527     CORBA::Object_var objComponent=((SalomeComponent*)_component)->getCompoPtr();
528     Engines::EngineComponent_var compo=Engines::EngineComponent::_narrow(objComponent);
529
530     // Set component properties
531     std::map<std::string,std::string> amap=getProperties();
532     if(amap.size() > 0)
533       {
534         Engines::FieldsDict_var dico = new Engines::FieldsDict;
535         dico->length(amap.size());
536         std::map<std::string,std::string>::const_iterator it;
537         int i=0;
538         for(it = amap.begin(); it != amap.end(); ++it)
539           {
540             dico[i].key=CORBA::string_dup(it->first.c_str());
541             dico[i].value <<=it->second.c_str();
542             i++;
543           }
544         compo->setProperties(dico);
545       }
546
547     //DII request building :
548     // a service gets all its in parameters first
549     // then all its out parameters
550     // no inout parameters
551     // the return value (if any) is the first out parameter
552     //
553     CORBA::Request_var req ;
554     try
555       {
556         req = objComponent->_request(_method.c_str());
557       }
558     catch(CORBA::SystemException& ex)
559       {
560         std::string msg="component '" +_ref+ "' has no service '" + _method+ "'";
561         _errorDetails=msg;
562         throw Exception(msg);
563       }
564     CORBA::NVList_ptr arguments = req->arguments() ;
565
566     DEBTRACE( "+++++++++++++++++SalomeNode::inputs+++++++++++++++++" );
567     int in_param=0;
568     //in parameters
569     list<InputPort *>::iterator iter2;
570     for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
571     {
572           InputCorbaPort *p=(InputCorbaPort *)*iter2;
573           if(p->edGetType()->isA(Runtime::_tc_file))
574             continue;
575           DEBTRACE( "port name: " << p->getName() );
576           DEBTRACE( "port kind: " << p->edGetType()->kind() );
577           CORBA::Any* ob=p->getAny();
578 #ifdef _DEVDEBUG_
579           CORBA::TypeCode_var tc=ob->type();
580           switch(p->edGetType()->kind())
581           {
582           case Double:
583             CORBA::Double d;
584             *ob >>= d;
585             DEBTRACE( d )
586             break;
587           case Int:
588             CORBA::Long l;
589             *ob >>= l;
590             DEBTRACE( l )
591             break;
592           case String:
593             const char *s;
594             *ob >>= s;
595             DEBTRACE( s )
596             break;
597           case Objref:
598             DEBTRACE( tc->id() )
599             break;
600           default:
601             break;
602           }
603 #endif
604           //add_value makes a copy of any. Copy will be deleted with request
605           arguments->add_value( p->getName().c_str() , *ob , CORBA::ARG_IN ) ;
606           in_param=in_param+1;
607     }
608     //in files
609     int nfiles=0;
610     DEBTRACE("checkInputFilesToService: " << _method);
611     try
612       {
613         for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
614           {
615             InputCorbaPort *p=(InputCorbaPort *)*iter2;
616             if(!p->edGetType()->isA(Runtime::_tc_file))
617               continue;
618             std::string filename=p->getName();
619             // replace ':' by '.'. Needed because port name can not contain '.'
620             string::size_type debut =filename.find_first_of(':',0);
621             while(debut != std::string::npos)
622               {
623                  filename[debut]='.';
624                  debut=filename.find_first_of(':',debut);
625               }
626             DEBTRACE( "inport with file: " << filename );
627             Engines::Salome_file_var isf=compo->setInputFileToService(_method.c_str(),p->getName().c_str());
628             isf->setDistributedFile(filename.c_str());
629             Engines::Salome_file_ptr osf;
630             CORBA::Any* any=p->getAny();
631             *any >>= osf;
632             isf->connect(osf);
633             nfiles++;
634           }
635         if(nfiles)
636           compo->checkInputFilesToService(_method.c_str());
637       }
638     catch( const SALOME::SALOME_Exception& ex )
639       {
640         std::string text="Execution problem in checkInputFilesToService: ";
641         text += (const char*)ex.details.text;
642         _errorDetails=text;
643         throw Exception(text);
644       }
645     catch(CORBA::SystemException& ex)
646       {
647         std::string msg="Execution problem: component probably does not support files ??";
648         _errorDetails=msg;
649         throw Exception(msg);
650       }
651     
652     //out parameters
653     DEBTRACE( "+++++++++++++++++SalomeNode::outputs+++++++++++++++++" )
654     list<OutputPort *>::iterator iter;
655     for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
656     {
657           OutputCorbaPort *p=(OutputCorbaPort *)*iter;
658           DEBTRACE( "port name: " << p->getName() )
659           DEBTRACE( "port kind: " << p->edGetType()->kind() )
660           if(p->edGetType()->isA(Runtime::_tc_file))
661             continue;
662           CORBA::Any* ob=p->getAnyOut();
663           //add_value makes a copy of any. Copy will be deleted with request
664           arguments->add_value( p->getName().c_str() , *ob , CORBA::ARG_OUT );
665           delete ob;
666     }
667
668     //return value
669     //if return type is set to void (not mandatory, it's set by default)
670     //the return value will not be marshalled as a return value but 
671     //as the first out argument (don't forget to add it as the first output argument)
672     req->set_return_type(CORBA::_tc_void);
673     //user exceptions
674     req->exceptions()->add(SALOME::_tc_SALOME_Exception);
675     
676     DEBTRACE( "+++++++++++++++++SalomeNode::calculation+++++++++++++++++" << _method )
677     req->invoke();
678     CORBA::Exception *exc =req->env()->exception();
679     if( exc )
680     {
681       DEBTRACE( "An exception was thrown!" )
682       DEBTRACE( "The raised exception is of Type:" << exc->_name() )
683
684       CORBA::SystemException* sysexc;
685       sysexc=CORBA::SystemException::_downcast(exc);
686       if(sysexc != NULL)
687         {
688           // It's a SystemException
689           DEBTRACE( "minor code: " << sysexc->minor() );
690           DEBTRACE( "completion code: " << sysexc->completed() );
691           std::string text="Execution problem: ";
692           std::string excname=sysexc->_name();
693           if(excname == "BAD_OPERATION")
694             {
695               text=text+"component '" +_ref+ "' has no service '" + _method+ "'";
696             }
697           else if(excname == "BAD_PARAM")
698             {
699               text=text+"A parameter (input or output) passed to the call is out of range or otherwise considered illegal.\n";
700               text=text+"Minor code: "+sysexc->NP_minorString();
701             }
702           else if(excname == "MARSHAL" && sysexc->minor() == omni::MARSHAL_PassEndOfMessage)
703             {
704               text=text+"probably an error in arguments of service '" + _method + "' from component '" +_ref+ "'";
705             }
706           else if(excname == "COMM_FAILURE" && sysexc->minor() == omni::COMM_FAILURE_UnMarshalResults)
707             {
708               text=text+"probably an error in output arguments of service '" + _method + "' from component '" +_ref+ "'";
709             }
710           else if(excname == "COMM_FAILURE" && sysexc->minor() == omni::COMM_FAILURE_UnMarshalArguments)
711             {
712               text=text+"probably an error in input arguments of service '" + _method + "' from component '" +_ref+ "'";
713             }
714           else if(excname == "COMM_FAILURE" && sysexc->minor() == omni::COMM_FAILURE_WaitingForReply)
715             {
716               text=text+"probably an error in input arguments of service '" + _method + "' from component '" +_ref+ "'";
717             }
718           else
719             {
720               DEBTRACE(sysexc->NP_minorString() );
721               text=text+"System Exception "+ excname;
722             }
723           _errorDetails=text;
724           throw Exception(text);
725         }
726
727       // Not a System Exception
728       CORBA::UnknownUserException* userexc;
729       userexc=CORBA::UnknownUserException::_downcast(exc);
730       if(userexc != NULL)
731         {
732           CORBA::Any anyExcept = userexc->exception(); 
733
734           const SALOME::SALOME_Exception* salexc;
735           if(anyExcept >>= salexc)
736             {
737               DEBTRACE("SALOME_Exception: "<< salexc->details.sourceFile);
738               DEBTRACE("SALOME_Exception: "<<salexc->details.lineNumber);
739               _errorDetails=salexc->details.text;
740               throw Exception("Execution problem: Salome Exception occurred" + getErrorDetails() );
741             }
742           std::string msg="Execution problem: User Exception occurred";
743           _errorDetails=msg;
744           throw Exception(msg);
745         }
746       std::string msg="Execution problem";
747       _errorDetails=msg;
748       throw Exception(msg);
749     }
750     
751     DEBTRACE( "++++++++++++SalomeNode::outputs++++++++++++" )
752     int out_param=in_param;
753     for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
754     {
755           OutputCorbaPort *p=(OutputCorbaPort *)*iter;
756           DEBTRACE( "port name: " << p->getName() );
757           DEBTRACE( "port kind: " << p->edGetType()->kind() );
758           DEBTRACE( "port number: " << out_param );
759           if(p->edGetType()->isA(Runtime::_tc_file))
760             continue;
761           CORBA::Any *ob=arguments->item(out_param)->value();
762 #ifdef _DEVDEBUG_
763       switch(p->edGetType()->kind())
764       {
765         case Double:
766           CORBA::Double d;
767           *ob >>= d;
768           DEBTRACE( d )
769           break;
770         case Int:
771           CORBA::Long l;
772           *ob >>= l;
773           DEBTRACE( l )
774           break;
775         case String:
776           const char *s;
777           *ob >>= s;
778           DEBTRACE( s )
779           break;
780         default:
781           break;
782       }
783 #endif
784         //OutputPort must copy the input Any(ob). 
785         //This Any will be deleted with the request.
786         //Copy is made by the method put.
787         p->put(ob);
788         out_param=out_param+1;
789     }
790
791     //Out files
792     nfiles=0;
793     DEBTRACE("checkOutputFilesToService: " << _method);
794     try
795       {
796         for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
797           {
798             OutputCorbaPort *p=(OutputCorbaPort *)*iter;
799             if(!p->edGetType()->isA(Runtime::_tc_file))
800               continue;
801             // The output port has a file object : special treatment
802             std::string filename=p->getName();
803             // replace ':' by '.'. Needed because port name can not contain '.'
804             string::size_type debut =filename.find_first_of(':',0);
805             while(debut != std::string::npos)
806               {
807                  filename[debut]='.';
808                  debut=filename.find_first_of(':',debut);
809               }
810             DEBTRACE( "outport with file: " << filename );
811             Engines::Salome_file_var osf=compo->setOutputFileToService(_method.c_str(),p->getName().c_str());
812             osf->setLocalFile(filename.c_str());
813             CORBA::Any any;
814             any <<= osf;
815             p->put(&any);
816           }
817         if(nfiles)
818           compo->checkOutputFilesToService(_method.c_str());
819       }
820     catch( const SALOME::SALOME_Exception& ex )
821       {
822         std::string text=(const char*)ex.details.text;
823         _errorDetails=text;
824         throw Exception("Execution problem in checkOutputFilesToService: " + text);
825       }
826     catch(CORBA::SystemException& ex)
827       {
828         std::string msg="Execution problem: component probably does not support files ?";
829         _errorDetails=msg;
830         throw Exception(msg);
831       }
832   }
833   //Request has been deleted (_var )
834   //All anys given to the request are deleted : don't forget to copy them 
835   //if you want to keep them
836   DEBTRACE( "+++++++++++++++++ End SalomeNode::execute: " << getName() << " +++++++++++++++++" )
837 }
838
839 Node *SalomeNode::simpleClone(ComposedNode *father, bool editionOnly) const
840 {
841   return new SalomeNode(*this,father);
842 }
843
844 //! Create a SalomeNode with the same component object and no input or output port
845 /*!
846  *   \param name : node name
847  *   \return       a new SalomeNode node
848  */
849 ServiceNode* SalomeNode::createNode(const std::string& name)
850 {
851   SalomeNode* node=new SalomeNode(name);
852   node->setComponent(_component);
853   return node;
854 }
855
856 std::string SalomeNode::getContainerLog()
857 {
858   std::string msg="Component is not loaded";
859   try
860     {
861       CORBA::Object_var objComponent=((SalomeComponent*)_component)->getCompoPtr();
862       Engines::EngineComponent_var compo=Engines::EngineComponent::_narrow(objComponent);
863       if( !CORBA::is_nil(compo) )
864         {
865           Engines::Container_var cont= compo->GetContainerRef();
866           CORBA::String_var logname = cont->logfilename();
867           DEBTRACE(logname);
868           msg=logname;
869           std::string::size_type pos = msg.find(":");
870           msg=msg.substr(pos+1);
871         }
872     }
873   catch(CORBA::COMM_FAILURE& ex) 
874     {
875       msg = ":Component no longer reachable: Caught system exception COMM_FAILURE";
876       msg += " -- unable to contact the object.";
877     }
878   catch(CORBA::SystemException& ex) 
879     {
880       msg = ":Component no longer reachable: Caught a CORBA::SystemException.\n";
881       CORBA::Any tmp;
882       tmp <<= ex;
883       CORBA::TypeCode_var tc = tmp.type();
884       const char *p = tc->name();
885       if ( *p != '\0' ) 
886         msg += p;
887       else  
888         msg += tc->id();
889     }
890   catch(CORBA::Exception& ex) 
891     {
892       msg = ":Component no longer reachable: Caught CORBA::Exception.\n";
893       CORBA::Any tmp;
894       tmp <<= ex;
895       CORBA::TypeCode_var tc = tmp.type();
896       const char *p = tc->name();
897       if ( *p != '\0' ) 
898         msg += p;
899       else  
900         msg += tc->id();
901     }
902   catch(omniORB::fatalException& fe) 
903     {
904       msg = ":Component no longer reachable: Caught omniORB::fatalException.\n";
905       stringstream log;
906       log << "  file: " << fe.file() << endl;
907       log << "  line: " << fe.line() << endl;
908       log << "  mesg: " << fe.errmsg() << endl;
909       msg += log.str();
910     }
911   catch(...) 
912     {
913       msg = ":Component no longer reachable: Caught unknown exception.";
914     }
915   return msg;
916 }
917
918 void SalomeNode::shutdown(int level)
919 {
920   DEBTRACE("SalomeNode::shutdown " << level);
921   if(_component)
922     _component->shutdown(level);
923 }