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