Salome HOME
Properly set sys.argv in Python interpreter when using driver executable
[modules/yacs.git] / src / runtime / RuntimeSALOME.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 #include <omniORB4/internal/corbaOrb.h>
28 #endif
29
30 #include "yacsconfig.h"
31 #include "YACS_version.h"
32 #include "RuntimeSALOME.hxx"
33 #include "SALOMEDispatcher.hxx"
34 #include "Proc.hxx"
35 #include "TypeCode.hxx"
36 #include "WhileLoop.hxx"
37 #include "ForLoop.hxx"
38 #include "SalomeOptimizerLoop.hxx"
39 #include "Bloc.hxx"
40 #include "InputPort.hxx"
41 #include "OutputPort.hxx"
42 #include "PresetPorts.hxx"
43 #include "InputDataStreamPort.hxx"
44 #include "OutputDataStreamPort.hxx"
45 #include "SalomeProc.hxx"
46 #include "PyStdout.hxx"
47 //Catalog Loaders
48 #include "SessionCataLoader.hxx"
49
50 //Components
51 #include "CORBAComponent.hxx"
52 #include "SalomeComponent.hxx"
53 #include "SalomePythonComponent.hxx"
54 #include "CppComponent.hxx"
55
56 #include "SalomeContainer.hxx"
57 #include "CppContainer.hxx"
58
59 //Nodes
60 #include "PythonNode.hxx"
61 #include "CORBANode.hxx"
62 #include "XMLNode.hxx"
63 #include "CppNode.hxx"
64 #include "PresetNode.hxx"
65 #include "OutNode.hxx"
66 #include "StudyNodes.hxx"
67 #include "SalomePythonNode.hxx"
68 #include "DistributedPythonNode.hxx"
69
70 //CORBA proxy ports
71 #include "CORBACORBAConv.hxx"
72 #include "CORBAPythonConv.hxx"
73 #include "CORBAXMLConv.hxx"
74 #include "CORBACppConv.hxx"
75 #include "CORBANeutralConv.hxx"
76
77 #include "TypeConversions.hxx"
78 //Python proxy ports
79 #include "PythonCORBAConv.hxx"
80 #include "PythonXMLConv.hxx"
81 #include "PythonCppConv.hxx"
82 #include "PythonNeutralConv.hxx"
83 #include "PythonInitConv.hxx"
84
85 //Neutral proxy ports
86 #include "NeutralCORBAConv.hxx"
87 #include "NeutralPythonConv.hxx"
88 #include "NeutralXMLConv.hxx"
89 #include "NeutralCppConv.hxx"
90 #include "NeutralInitConv.hxx"
91
92 //C++ proxy ports
93 #include "CppCORBAConv.hxx"
94 #include "CppPythonConv.hxx"
95 #include "CppXMLConv.hxx"
96 #include "CppCppConv.hxx"
97 #include "CppNeutralConv.hxx"
98
99 //XML proxy ports
100 #include "XMLCORBAConv.hxx"
101 #include "XMLPythonConv.hxx"
102 #include "XMLCppConv.hxx"
103 #include "XMLNeutralConv.hxx"
104
105 //Calcium specific ports
106 #include "CalStreamPort.hxx"
107
108 #ifdef SALOME_KERNEL
109 #include "SALOME_NamingService.hxx"
110 #include "SALOME_LifeCycleCORBA.hxx"
111 #endif
112   
113 #include <libxml/parser.h>
114 #include <omniORB4/CORBA.h>
115 #include <iostream>
116 #include <sstream>
117 #include <cassert>
118
119 //#define _DEVDEBUG_
120 #include "YacsTrace.hxx"
121
122 using namespace std;
123 using namespace YACS::ENGINE;
124
125 void RuntimeSALOME::setRuntime(long flags, int argc, char* argv[]) // singleton creation (not thread safe!)
126 {
127   if (! Runtime::_singleton)
128     {
129       RuntimeSALOME* r=new RuntimeSALOME(flags, argc, argv);
130       Runtime::_singleton = r;
131       r->initBuiltins();
132     }
133   DEBTRACE("RuntimeSALOME::setRuntime() done !");
134 }
135
136 RuntimeSALOME* YACS::ENGINE::getSALOMERuntime()
137 {
138   YASSERT(Runtime::_singleton);
139   return dynamic_cast< RuntimeSALOME* >(Runtime::_singleton);
140 }
141
142 /**
143  *  Singleton creation, initialize converter map
144  */
145   
146 RuntimeSALOME::RuntimeSALOME()
147 {
148   YASSERT(0);
149 }
150
151 void RuntimeSALOME::initBuiltins()
152 {
153   //Fill the builtin catalog with nodes specific to the runtime
154   std::map<std::string,TypeCode*>& typeMap=_builtinCatalog->_typeMap;
155   std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
156   std::map<std::string,ComposedNode*>& composednodeMap=_builtinCatalog->_composednodeMap;
157   std::map<std::string,ComponentDefinition*>& componentMap=_builtinCatalog->_componentMap;
158   nodeMap["PyFunction"]=new PyFuncNode("PyFunction");
159   nodeMap["PyScript"]=new PythonNode("PyScript");
160   nodeMap["CORBANode"]=new CORBANode("CORBANode");
161   nodeMap["XmlNode"]=new XmlNode("XmlNode");
162   nodeMap["SalomeNode"]=new SalomeNode("SalomeNode");
163   nodeMap["CppNode"]=new CppNode("CppNode");
164   nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode");
165   nodeMap["PresetNode"]=new PresetNode("PresetNode");
166   nodeMap["OutNode"]=new OutNode("OutNode");
167   nodeMap["StudyInNode"]=new StudyInNode("StudyInNode");
168   nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode");
169   composednodeMap["OptimizerLoop"]=createOptimizerLoop("OptimizerLoop","","",true);
170   typeMap["dblevec"]= createSequenceTc("dblevec","dblevec",_tc_double);
171   typeMap["intvec"]= createSequenceTc("intvec","intvec",_tc_int);
172   typeMap["stringvec"]= createSequenceTc("stringvec","stringvec",_tc_string);
173   typeMap["boolvec"]= createSequenceTc("boolvec","boolvec",_tc_bool);
174   typeMap["seqdblevec"]= createSequenceTc("seqdblevec","seqdblevec",typeMap["dblevec"]);
175   typeMap["seqintvec"]= createSequenceTc("seqintvec","seqintvec",typeMap["intvec"]);
176   typeMap["seqstringvec"]= createSequenceTc("seqstringvec","seqstringvec",typeMap["stringvec"]);
177   typeMap["seqboolvec"]= createSequenceTc("seqboolvec","seqboolvec",typeMap["boolvec"]);
178   std::list<TypeCodeObjref *> ltc;
179   typeMap["pyobj"]= createInterfaceTc("python:obj:1.0","pyobj",ltc);
180   ENGINE::TypeCodeStruct *t = createStructTc("","Engines/dataref");
181   t->addMember("ref",_tc_string);
182   typeMap["dataref"]= t;
183 }
184
185 RuntimeSALOME::RuntimeSALOME(long flags, int argc, char* argv[])
186 {
187   // If all flags (apart the IsPyExt flags) are unset, force them to true
188   if ((flags - flags & RuntimeSALOME::IsPyExt) == 0)
189     flags += RuntimeSALOME::UseCorba + RuntimeSALOME::UsePython
190           +  RuntimeSALOME::UseCpp + RuntimeSALOME::UseXml;
191
192   // Salome Nodes implies Corba Nodes
193   if (flags & RuntimeSALOME::UseSalome)
194     flags |= RuntimeSALOME::UseCorba;
195
196   // Corba Nodes implies Python Nodes
197   if (flags & RuntimeSALOME::UseCorba)
198     flags |= RuntimeSALOME::UsePython;
199
200   _useCorba = flags & RuntimeSALOME::UseCorba;
201   _usePython = flags & RuntimeSALOME::UsePython;
202   _useCpp = flags & RuntimeSALOME::UseCpp;
203   _useXml = flags & RuntimeSALOME::UseXml;
204
205   /* Init libxml */
206   xmlInitParser();
207
208   if (_useCpp)    _setOfImplementation.insert(CppNode::IMPL_NAME);
209   if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME);
210   if (_useCorba)  _setOfImplementation.insert(CORBANode::IMPL_NAME);
211   if (_useXml)    _setOfImplementation.insert(XmlNode::IMPL_NAME);
212   init(flags, argc, argv);
213 }
214
215 RuntimeSALOME::~RuntimeSALOME()
216 {
217   DEBTRACE("RuntimeSALOME::~RuntimeSALOME");
218   // destroy catalog loader prototypes
219   std::map<std::string, CatalogLoader*>::const_iterator pt;
220   for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++)
221     {
222       delete (*pt).second;
223     }
224 }
225
226 //! CORBA and Python initialization
227 /*!
228  *  \param flags contains several bits
229  *            bit0 (ispyext) true when method is called from Python
230  *                           (Python initialization must not be done!)
231  *            bit1 (UsePython) true if python nodes are needed
232  *            bit1 (UseCorba)  true if CORBA nodes are needed
233  *            bit1 (UseXml)    true if python nodes are needed
234  *            bit1 (UseCpp)    true if C++ nodes are needed
235  *            bit1 (UseSalome) true if Salome nodes are needed
236  *
237  */
238
239 void RuntimeSALOME::init(long flags, int argc, char* argv[])
240 {
241   bool ispyext = flags & RuntimeSALOME::IsPyExt;
242   if (_useCorba)
243     {
244       PortableServer::POA_var root_poa;
245       PortableServer::POAManager_var pman;
246       CORBA::Object_var obj;
247       int nbargs = 0; char **args = 0;
248       _orb = CORBA::ORB_init (nbargs, args);
249       obj = _orb->resolve_initial_references("RootPOA");
250       root_poa = PortableServer::POA::_narrow(obj);
251       pman = root_poa->the_POAManager();
252       pman->activate();
253
254 #ifdef REFCNT
255       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
256 #endif
257       obj = _orb->resolve_initial_references("DynAnyFactory");
258       _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj);
259     }
260
261   if (_usePython)
262     {
263       DEBTRACE("RuntimeSALOME::init, is python extension = " << ispyext);
264
265       // Initialize Python interpreter in embedded mode
266       if (!Py_IsInitialized())
267         {
268 #if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
269           Py_Initialize(); 
270 #else
271           Py_InitializeEx(0); // do not install signal handlers
272 #endif
273           PySys_SetArgv(argc, argv);
274           PyEval_InitThreads(); /* Create (and acquire) the interpreter lock (for threads)*/
275           PyEval_SaveThread(); /* Release the thread state */
276           //here we do not have the Global Interpreter Lock
277         }
278
279       PyObject *mainmod,*pyapi,*res ;
280       PyObject *globals;
281       PyGILState_STATE gstate;
282       gstate = PyGILState_Ensure(); // acquire the Global Interpreter Lock
283     
284       mainmod = PyImport_AddModule("__main__");
285       globals = PyModule_GetDict(mainmod);
286       /* globals is a borrowed reference */
287   
288       if (PyDict_GetItemString(globals, "__builtins__") == NULL) 
289         {
290           PyObject *bimod = PyImport_ImportModule("__builtin__");
291           if (bimod == NULL || PyDict_SetItemString(globals, "__builtins__", bimod) != 0)
292             Py_FatalError("can't add __builtins__ to __main__");
293           Py_DECREF(bimod);
294         }
295
296       _bltins = PyEval_GetBuiltins();  /* borrowed ref */
297
298       if (_useCorba)
299         {
300
301           //init section
302           _omnipy = PyImport_ImportModule((char*)"_omnipy");
303           if (!_omnipy)
304             {
305               PyErr_Print();
306               PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy");
307               goto out;
308             }
309           pyapi = PyObject_GetAttrString(_omnipy, (char*)"API");
310           if (!pyapi)
311             {
312               goto out;
313             }
314           _api = (omniORBpyAPI*)PyCObject_AsVoidPtr(pyapi);
315           Py_DECREF(pyapi);
316
317           res=PyRun_String("\n"
318                            "from math import *\n"
319                            "import sys\n"
320                            "sys.path.insert(0,'.')\n"
321                            "from omniORB import CORBA\n"
322                            "from omniORB import any\n"
323                            "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n"
324                            "#print sys.getrefcount(orb)\n"
325                            "try:\n"
326                            "  import SALOME\n"
327                            "except:\n"
328                            "  pass\n"
329                            "\n",
330                            Py_file_input,globals,globals );
331           if(res == NULL)
332             {
333               PyErr_Print();
334               goto out;
335             }
336           Py_DECREF(res);
337
338           _pyorb = PyDict_GetItemString(globals,"orb");
339           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref _pyorb */
340
341           PyObject *pyany;
342           pyany = PyDict_GetItemString(globals,"any");
343           /* PyDict_GetItemString returns a borrowed reference. There is no need to decref pyany */
344
345 #ifdef REFCNT
346           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
347 #endif
348         }
349       out:
350         PyGILState_Release(gstate); // Release the Global Interpreter Lock
351     }
352   if (_useCorba)
353     {
354       // initialize the catalogLoaderFactory map with the session one
355       _catalogLoaderFactoryMap["session"]=new SessionCataLoader;
356     }
357 }
358
359 void RuntimeSALOME::fini()
360 {
361   if (_usePython)
362     {
363       PyGILState_STATE gstate = PyGILState_Ensure();
364 #ifdef REFCNT
365       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
366 #endif
367       PyObject *mainmod, *globals;
368       mainmod = PyImport_AddModule("__main__");
369       globals = PyModule_GetDict(mainmod);
370       if (_useCorba)
371         {
372           PyObject* res;
373           res=PyRun_String("orb.destroy()\n"
374                            "\n",
375                            Py_file_input,globals,globals );
376           if(res == NULL)
377             PyErr_Print();
378           else
379             Py_DECREF(res);
380         }
381       std::map<std::string,Node*>& nodeMap=_builtinCatalog->_nodeMap;
382       delete nodeMap["PyFunction"];
383       delete nodeMap["PyScript"];
384       delete nodeMap["SalomePythonNode"];
385       nodeMap.erase("PyFunction");
386       nodeMap.erase("PyScript");
387       nodeMap.erase("SalomePythonNode");
388
389       Py_Finalize();
390 #ifdef REFCNT
391       DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
392 #endif
393     }
394   else
395     {
396       if (_useCorba)
397         {
398 #ifdef REFCNT
399           DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount);
400 #endif
401           _orb->destroy();
402         }
403     }
404 }
405
406 std::string RuntimeSALOME::getVersion() const
407 {
408 #ifdef YACS_DEVELOPMENT
409   return CORBA::string_dup(YACS_VERSION_STR"dev");
410 #else
411   return CORBA::string_dup(YACS_VERSION_STR);
412 #endif
413 }
414
415 Proc* RuntimeSALOME::createProc(const std::string& name)
416 {
417   return new SalomeProc(name);
418 }
419
420 TypeCode * RuntimeSALOME::createInterfaceTc(const std::string& id, const std::string& name,
421                                             std::list<TypeCodeObjref *> ltc)
422 {
423   std::string myName;
424   if(id == "") myName = "IDL:" + name + ":1.0";
425   else myName = id;
426   return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc);
427 }
428
429 TypeCode * RuntimeSALOME::createSequenceTc(const std::string& id,
430                                            const std::string& name,
431                                            TypeCode *content)
432 {
433   return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
434 };
435
436 TypeCodeStruct * RuntimeSALOME::createStructTc(const std::string& id, const std::string& name)
437 {
438   std::string myName;
439   if(id == "") myName = "IDL:" + name + ":1.0";
440   else myName = id;
441   return (TypeCodeStruct *)TypeCode::structTc(myName.c_str(),name.c_str());
442 }
443
444 Bloc* RuntimeSALOME::createBloc(const std::string& name)
445 {
446   return new Bloc(name);
447 }
448
449 WhileLoop* RuntimeSALOME::createWhileLoop(const std::string& name)
450 {
451   return new WhileLoop(name);
452 }
453
454 ForLoop* RuntimeSALOME::createForLoop(const std::string& name)
455 {
456   return new ForLoop(name);
457 }
458
459 OptimizerLoop* RuntimeSALOME::createOptimizerLoop(const std::string& name,const std::string& algLib,const std::string& factoryName,
460                                                   bool algInitOnFile, const std::string& kind, Proc * procForTypes)
461 {
462   OptimizerLoop * ol = (kind == "base") ? new OptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes) :
463                                           new SalomeOptimizerLoop(name,algLib,factoryName,algInitOnFile, true, procForTypes);
464   ol->edGetNbOfBranchesPort()->edInit(1);
465   return ol;
466 }
467
468 DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name)
469 {
470   DataNode* node;
471   if(kind == "" )
472     {
473       node = new PresetNode(name);
474       return node;
475     }
476   else if(kind == "study" )
477     {
478       return new StudyInNode(name);
479     }
480   std::string msg="DataNode kind ("+kind+") unknown";
481   throw Exception(msg);
482 }
483
484 DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name)
485 {
486   if(kind == "" )
487     {
488       return new OutNode(name);
489     }
490   else if(kind == "study" )
491     {
492       return new StudyOutNode(name);
493     }
494
495   std::string msg="OutDataNode kind ("+kind+") unknown";
496   throw Exception(msg);
497 }
498
499 InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name)
500 {
501   InlineFuncNode* node;
502   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
503     {
504       node = new PyFuncNode(name);
505       return node;
506     }
507   if(kind == DistributedPythonNode::KIND)
508     return new DistributedPythonNode(name);
509   std::string msg="FuncNode kind ("+kind+") unknown";
510   throw Exception(msg);
511 }
512
513 InlineNode* RuntimeSALOME::createScriptNode(const std::string& kind,const std::string& name)
514 {
515   InlineNode* node;
516   if(kind == "" || kind == SalomeNode::KIND || kind == PythonNode::KIND)
517     {
518       node = new PythonNode(name);
519       return node;
520     }
521   std::string msg="ScriptNode kind ("+kind+") unknown";
522   throw Exception(msg);
523 }
524
525 ServiceNode* RuntimeSALOME::createRefNode(const std::string& kind,const std::string& name)
526 {
527   ServiceNode* node;
528   if(kind == "" || kind == SalomeNode::KIND || kind == CORBANode::KIND)
529     {
530       node = new CORBANode(name);
531       return node;
532     }
533   else if(kind == XmlNode::KIND)
534     {
535       node = new XmlNode(name);
536       return node;
537     }
538   std::string msg="RefNode kind ("+kind+") unknown";
539   throw Exception(msg);
540 }
541
542 ServiceNode* RuntimeSALOME::createCompoNode(const std::string& kind,const std::string& name)
543 {
544   ServiceNode* node;
545   if(kind == "" || kind == SalomeNode::KIND )
546     {
547       node=new SalomeNode(name);
548       return node;
549     }
550   else if (kind == CppNode::KIND) 
551     {
552       node = new CppNode(name);
553       return node;
554     }
555   std::string msg="CompoNode kind ("+kind+") unknown";
556   throw Exception(msg);
557 }
558
559 ServiceInlineNode *RuntimeSALOME::createSInlineNode(const std::string& kind, const std::string& name)
560 {
561   if(kind == "" || kind == SalomeNode::KIND )
562     return new SalomePythonNode(name);
563   std::string msg="CompoNode kind ("+kind+") unknown";
564   throw Exception(msg);
565 }
566
567 ComponentInstance* RuntimeSALOME::createComponentInstance(const std::string& name,
568                                                           const std::string& kind)
569 {
570   ComponentInstance* compo;
571   if(kind == "" || kind == SalomeComponent::KIND) 
572     return new SalomeComponent(name);
573   else if(kind == CORBAComponent::KIND)
574     return new CORBAComponent(name);
575   else if(kind == SalomePythonComponent::KIND)
576     return new SalomePythonComponent(name);
577   else if (kind == CppComponent::KIND)
578     return new CppComponent(name);
579   std::string msg="Component Instance kind ("+kind+") unknown";
580   throw Exception(msg);
581 }
582
583 Container *RuntimeSALOME::createContainer(const std::string& kind)
584 {
585   if(kind == "" || kind == SalomeComponent::KIND)
586     return new SalomeContainer;
587   else if (kind == CppComponent::KIND)
588     return new CppContainer;
589   std::string msg="Container kind ("+kind+") unknown";
590   throw Exception(msg);
591 }
592
593 InputPort * RuntimeSALOME::createInputPort(const std::string& name,
594                                            const std::string& impl,
595                                            Node * node,
596                                            TypeCode * type)
597 {
598   if(impl == CppNode::IMPL_NAME)
599     {
600       return new InputCppPort(name, node, type);
601     }
602   else if(impl == PythonNode::IMPL_NAME)
603     {
604       return new InputPyPort(name, node, type);
605     }
606   else if(impl == CORBANode::IMPL_NAME)
607     {
608       return new InputCorbaPort(name, node, type);
609     }
610   else if(impl == XmlNode::IMPL_NAME)
611     {
612       return new InputXmlPort(name, node, type);
613     }
614   else
615     {
616       stringstream msg;
617       msg << "Cannot create " << impl << " InputPort" ;
618       msg << " ("__FILE__ << ":" << __LINE__ << ")";
619       throw Exception(msg.str());
620     }
621 }
622
623 OutputPort * RuntimeSALOME::createOutputPort(const std::string& name,
624                                              const std::string& impl,
625                                              Node * node,
626                                              TypeCode * type)
627 {
628   if(impl == CppNode::IMPL_NAME)
629     {
630       return new OutputCppPort(name, node, type);
631     }
632   else if(impl == PythonNode::IMPL_NAME)
633     {
634       return new OutputPyPort(name, node, type);
635     }
636   else if(impl == CORBANode::IMPL_NAME)
637     {
638       return new OutputCorbaPort(name, node, type);
639     }
640   else if(impl == XmlNode::IMPL_NAME)
641     {
642       return new OutputXmlPort(name, node, type);
643     }
644   else
645     {
646       stringstream msg;
647       msg << "Cannot create " << impl << " OutputPort" ;
648       msg << " ("__FILE__ << ":" << __LINE__ << ")";
649       throw Exception(msg.str());
650     }
651 }
652
653 InputDataStreamPort* RuntimeSALOME::createInputDataStreamPort(const std::string& name,
654                                                               Node *node,TypeCode *type)
655 {
656   DEBTRACE("createInputDataStreamPort: " << name << " " << type->shortName());
657   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
658     {
659       return new InputCalStreamPort(name,node,type);
660     }
661   else
662     {
663       return new InputDataStreamPort(name,node,type);
664     }
665 }
666
667 OutputDataStreamPort* RuntimeSALOME::createOutputDataStreamPort(const std::string& name,
668                                                                 Node *node,TypeCode *type)
669 {
670   DEBTRACE("createOutputDataStreamPort: " << name << " " << type->shortName());
671   if(type->kind() == Objref && std::string(type->shortName(),7) == "CALCIUM")
672     {
673       return new OutputCalStreamPort(name,node,type);
674     }
675   else
676     {
677       return new OutputDataStreamPort(name,node,type);
678     }
679 }
680
681 //! Main adapter function : adapt an InputPort to be able to connect it to an OutputPort with a possible different implementation 
682 /*!
683  *  \param source : InputPort to be adapted
684  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
685  *  \param type : data type provided by the InputPort
686  *  \param init : indicates if the adapted InputPort will be used for initialization (value true) or not (value false)
687  * 
688  * \return : adapted InputPort
689  */
690 InputPort* RuntimeSALOME::adapt(InputPort* source,
691                                 const std::string& impl,
692                                 TypeCode * type,bool init) throw (ConversionException)
693 {
694   string imp_source=source->getNode()->getImplementation();
695   if(imp_source == PythonNode::IMPL_NAME)
696     {
697       return adapt((InputPyPort*)source,impl,type,init);
698     }
699   else if(imp_source == CppNode::IMPL_NAME)
700     {
701       return adapt((InputCppPort*)source,impl,type,init);
702     }
703   else if(imp_source == CORBANode::IMPL_NAME)
704     {
705       return adapt((InputCorbaPort*)source,impl,type,init);
706     }
707   else if(imp_source == XmlNode::IMPL_NAME)
708     {
709       return adapt((InputXmlPort*)source,impl,type,init);
710     }
711   else if(imp_source == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
712     {
713       return adaptNeutral(source,impl,type,init);
714     }
715   else
716     {
717       stringstream msg;
718       msg << "Cannot adapt " << imp_source << " InputPort to " << impl;
719       msg << " ("__FILE__ << ":" << __LINE__ << ")";
720       throw ConversionException(msg.str());
721     }
722 }
723
724 //! Adapter function for InPropertyPort
725 /*!
726  *  \param source : InPropertyPort to be adapted
727  *  \param impl : new implementation (C++, python, CORBA, XML, Neutral)
728  *  \param type : data type provided by the InPropertyPort
729  *  \param init : indicates if the adapted InPropertyPort will be used for initialization (value true) or not (value false)
730  * 
731  * \return : adapted InputPort
732  */
733 InputPort* RuntimeSALOME::adapt(InPropertyPort* source,
734                                 const std::string& impl,
735                                 TypeCode * type,bool init) throw (ConversionException)
736 {
737   return adaptNeutral((InputPort *)source,impl,type,init);
738 }
739
740 //! Adapt a Neutral input port to a Corba output port
741 /*!
742  *   \param inport : Neutral input port to adapt to Corba type type
743  *   \param type : output port type
744  *   \return an adaptated input port of type InputCorbaPort
745  */
746 InputPort* RuntimeSALOME::adaptNeutralToCorba(InputPort* inport,
747                       TypeCode * type) throw (ConversionException)
748 {
749   // BEWARE : using the generic check
750   if(inport->edGetType()->isAdaptable(type))
751     {
752       //the output data is convertible to inport type
753       return new CorbaNeutral(inport);
754     }
755   //non convertible type
756   stringstream msg;
757   msg << "Cannot connect Corba output port with type: " << type->id() ;
758   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
759 #ifdef _DEVDEBUG_
760   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
761 #endif
762   throw ConversionException(msg.str());
763 }
764
765 //! Adapt a Neutral input port to a Python output port
766 /*!
767  *   \param inport : input port to adapt to Python type type
768  *   \param type : output port type
769  *   \return an adaptated input port of type InputPyPort
770  */
771 InputPort* RuntimeSALOME::adaptNeutralToPython(InputPort* inport,
772                       TypeCode * type) throw (ConversionException)
773 {
774   // BEWARE : using the generic check
775   if(inport->edGetType()->isAdaptable(type))
776     {
777       //convertible type
778       return new PyNeutral(inport);
779     }
780   //non convertible type
781   stringstream msg;
782   msg << "Cannot connect Python output port with type: " << type->id() ;
783   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
784 #ifdef _DEVDEBUG_
785   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
786 #endif
787   throw ConversionException(msg.str());
788 }
789
790 //! Adapt a Neutral input port to a Xml output port 
791 /*!
792  *   \param inport : input port to adapt to Xml type type
793  *   \param type : output port type
794  *   \return an input port of type InputXmlPort
795  */
796 InputPort* RuntimeSALOME::adaptNeutralToXml(InputPort* inport,
797                       TypeCode * type) throw (ConversionException)
798 {
799   // BEWARE : using the generic check
800   if(inport->edGetType()->isAdaptable(type))
801     {
802       //convertible type
803       return new XmlNeutral(inport);
804     }
805   //non convertible type
806   stringstream msg;
807   msg << "Cannot connect Xml output port with type: " << type->id() ;
808   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
809 #ifdef _DEVDEBUG_
810   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
811 #endif
812   throw ConversionException(msg.str());
813 }
814
815 //! Adapt a Neutral input port to a C++ output port 
816 /*!
817  *   \param inport : input port to adapt to C++ type type
818  *   \param type : output port type
819  *   \return an input port of type InputCppPort
820  */
821 InputPort* RuntimeSALOME::adaptNeutralToCpp(InputPort* inport,
822                       TypeCode * type) throw (ConversionException)
823 {
824   DEBTRACE("RuntimeSALOME::adaptNeutralToCpp(InputPort* inport" );
825   if(isAdaptableNeutralCpp(type,inport->edGetType()))
826     {
827       //convertible type
828       return new CppNeutral(inport);
829     }
830   //non convertible type
831   stringstream msg;
832   msg << "Cannot connect Cpp output port with type: " << type->id() ;
833   msg << " to Neutral input port " << inport->getName() << " with type: " << inport->edGetType()->id();
834 #ifdef _DEVDEBUG_
835   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
836 #endif
837   throw ConversionException(msg.str());
838 }
839
840 //! Adapt a Neutral input port to connect it to an output port with a given implementation
841 /*!
842  *   \param source : Neutral input port to adapt to implementation impl and type type
843  *   \param impl : output port implementation (C++, Python, Corba, Xml or Neutral)
844  *   \param type : output port supported type
845  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
846  *   \return       the adaptated port
847  */
848 InputPort* RuntimeSALOME::adaptNeutral(InputPort* source,
849                                        const std::string& impl,
850                                        TypeCode * type,bool init) throw (ConversionException)
851 {
852   if(impl == CppNode::IMPL_NAME)
853     {
854       return adaptNeutralToCpp(source,type);
855     }
856   else if(impl == PythonNode::IMPL_NAME)
857     {
858       return adaptNeutralToPython(source,type);
859     }
860   else if(impl == CORBANode::IMPL_NAME)
861     {
862       return adaptNeutralToCorba(source,type);
863     }
864   else if(impl == XmlNode::IMPL_NAME )
865     {
866       return adaptNeutralToXml(source,type);
867     }
868   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
869     {
870       if(init)
871         return new NeutralInit(source);
872       else
873         return new ProxyPort(source);
874     }
875   stringstream msg;
876   msg << "Cannot connect InputPort : unknown implementation " << impl;
877   msg << " (" <<__FILE__ << ":" <<__LINE__ << ")";
878   throw ConversionException(msg.str());
879 }
880
881 //! Adapt a XML input port to connect it to a CORBA output port 
882 /*!
883  *   \param inport : input port to adapt to CORBA type type
884  *   \param type : type supported by output port
885  *   \return an adaptator port of type InputCorbaPort 
886  */
887
888 InputPort* RuntimeSALOME::adaptXmlToCorba(InputXmlPort* inport,
889                                           TypeCode * type) throw (ConversionException)
890 {
891   if(isAdaptableXmlCorba(type,inport->edGetType()))
892     {
893       //output type is convertible to input type
894       return new CorbaXml(inport);
895     }
896   //output type is not convertible
897   stringstream msg;
898   msg << "Cannot connect Corba output port with type: " << type->id() ;
899   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
900 #ifdef _DEVDEBUG_
901   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
902 #endif
903   throw ConversionException(msg.str());
904 }
905
906 //! Adapt a XML input port to a Python output port
907 /*!
908  *   \param inport : input port to adapt to Python type type
909  *   \param type : output port type
910  *   \return an adaptated input port of type InputPyPort
911  */
912 InputPort* RuntimeSALOME::adaptXmlToPython(InputXmlPort* inport,
913                       TypeCode * type) throw (ConversionException)
914 {
915   if(inport->edGetType()->isAdaptable(type))
916     {
917       //the output data is convertible to inport type
918       return new PyXml(inport);
919     }
920   //non convertible type
921   stringstream msg;
922   msg << "Cannot connect Python output port with type: " << type->id() ;
923   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
924 #ifdef _DEVDEBUG_
925   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
926 #endif
927   throw ConversionException(msg.str());
928 }
929
930 //! Adapt a XML input port to a C++ output port
931 /*!
932  *   \param inport : input port to adapt to C++ type type
933  *   \param type : output port type
934  *   \return an adaptated input port of type InputPyPort
935  */
936 InputPort* RuntimeSALOME::adaptXmlToCpp(InputXmlPort* inport,
937                       TypeCode * type) throw (ConversionException)
938 {
939   DEBTRACE("RuntimeSALOME::adaptXmlToCpp(InputPort* inport" );
940   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
941   if(type->isAdaptable(inport->edGetType()))
942     {
943       //the output data is convertible to inport type
944       return new CppXml(inport);
945     }
946   //non convertible type
947   stringstream msg;
948   msg << "Cannot connect Cpp output port with type: " << type->id() ;
949   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
950 #ifdef _DEVDEBUG_
951   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
952 #endif
953   throw ConversionException(msg.str());
954 }
955
956 //! Adapt a XML input port to a Neutral output port
957 /*!
958  *   \param inport : input port to adapt to Neutral type type
959  *   \param type : output port type
960  *   \return an adaptated input port of type Neutralxxxx
961  */
962 InputPort* RuntimeSALOME::adaptXmlToNeutral(InputXmlPort* inport,
963                       TypeCode * type) throw (ConversionException)
964 {
965   if(inport->edGetType()->isAdaptable(type))
966     {
967       //the output data is convertible to inport type
968       return new NeutralXml(inport);
969     }
970   //non convertible type
971   stringstream msg;
972   msg << "Cannot connect Xml InputPort to OutputNeutralPort : " ;
973   msg << "(" <<__FILE__ << ":" <<__LINE__<< ")";
974   throw ConversionException(msg.str());
975 }
976
977 //! Adapt a XML input port to a Xml output port
978 /*!
979  *   \param inport : input port to adapt to Xml type type
980  *   \param type : output port type
981  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
982  *   \return an adaptated input port of type Xmlxxxx
983  */
984 InputPort* RuntimeSALOME::adaptXmlToXml(InputXmlPort* inport,
985                       TypeCode * type,bool init) throw (ConversionException)
986 {
987   if(init)
988     return new ProxyPort(inport);
989
990   if(inport->edGetType()->isAdaptable(type))
991     return new ProxyPort(inport);
992
993   stringstream msg;
994   msg << "Cannot connect Xml output port with type: " << type->id() ;
995   msg << " to Xml input port " << inport->getName() << " with type: " << inport->edGetType()->id();
996 #ifdef _DEVDEBUG_
997   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
998 #endif
999   throw ConversionException(msg.str());
1000 }
1001
1002 //! Adapt an Xml input port to an output port which implementation is given by impl
1003 /*!
1004  *   \param source : input port to adapt to implementation impl and type type
1005  *   \param impl : output port implementation (C++, Python or Corba)
1006  *   \param type : output port supported type
1007  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1008  *   \return       the adaptated port
1009  */
1010
1011 InputPort* RuntimeSALOME::adapt(InputXmlPort* source,
1012                                 const std::string& impl,
1013                                 TypeCode * type,bool init) throw (ConversionException)
1014 {
1015   if(impl == CORBANode::IMPL_NAME)
1016     {
1017       return adaptXmlToCorba(source,type);
1018     }
1019   else if(impl == PythonNode::IMPL_NAME)
1020     {
1021       return adaptXmlToPython(source,type);
1022     }
1023   else if(impl == CppNode::IMPL_NAME)
1024     {
1025       return adaptXmlToCpp(source,type);
1026     }
1027   else if(impl == XmlNode::IMPL_NAME )
1028     {
1029       return adaptXmlToXml(source,type,init);
1030     }
1031   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1032     {
1033       return adaptXmlToNeutral(source,type);
1034     }
1035   else
1036     {
1037       stringstream msg;
1038       msg << "Cannot connect InputXmlPort to " << impl << " implementation";
1039       msg << " ("__FILE__ << ":" << __LINE__ << ")";
1040       throw ConversionException(msg.str());
1041     }
1042 }
1043
1044
1045 //! Adapt a CORBA input port to a CORBA output port 
1046 /*!
1047  *   \param inport : input port to adapt to CORBA outport data type
1048  *   \param type : outport data type 
1049  *   \return an adaptator port of type InputCORBAPort 
1050  */
1051 InputPort* RuntimeSALOME::adaptCorbaToCorba(InputCorbaPort* inport,
1052                                             TypeCode * type) throw (ConversionException)
1053 {
1054   if(type->isA(inport->edGetType()))
1055     {
1056       //types are compatible : no conversion 
1057       //outport data type is more specific than inport required type
1058       //so the inport can be used safely 
1059       return new ProxyPort(inport);
1060     }
1061   else if(isAdaptableCorbaCorba(type,inport->edGetType()))
1062     {
1063       //ouport data can be converted to inport data type
1064       return new CorbaCorba(inport);
1065     }
1066   //outport data can not be converted
1067   stringstream msg;
1068   msg << "Cannot connect Corba output port with type: " << type->id() ;
1069   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1070 #ifdef _DEVDEBUG_
1071   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1072 #endif
1073   throw ConversionException(msg.str());
1074 }
1075
1076 //! Adapt a CORBA input port to a Python output port 
1077 /*!
1078  *   \param inport : input port to adapt to Python type type
1079  *   \param type : outport data type 
1080  *   \return an adaptator port of type InputPyPort 
1081  */
1082
1083 InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport,
1084                                              TypeCode * type) throw (ConversionException)
1085 {
1086   if(inport->edGetType()->kind() == Double)
1087     {
1088       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaDouble(inport);
1089     }
1090   else if(inport->edGetType()->kind() == Int)
1091     {
1092       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaInt(inport);
1093     }
1094   else if(inport->edGetType()->kind() == String)
1095     {
1096       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaString(inport);
1097     }
1098   else if(inport->edGetType()->kind() == Bool)
1099     {
1100       if(isAdaptableCorbaPyObject(type,inport->edGetType()))return new PyCorbaBool(inport);
1101     }
1102   else if(inport->edGetType()->kind() == Objref )
1103     {
1104       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1105         {
1106           return new PyCorbaObjref(inport);
1107         }
1108       else
1109         {
1110           stringstream msg;
1111           msg << "Cannot connect Python output port with type: " << type->id() ;
1112           msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id();
1113           msg << " (" << __FILE__ << ":" <<__LINE__ << ")";
1114           throw ConversionException(msg.str());
1115         }
1116     }
1117   else if(inport->edGetType()->kind() == Sequence)
1118     {
1119       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1120         {
1121           return new PyCorbaSequence(inport);
1122         }
1123       else
1124         {
1125           stringstream msg;
1126           msg << "Cannot convert this sequence type " ;
1127           msg << __FILE__ << ":" <<__LINE__;
1128           throw ConversionException(msg.str());
1129         }
1130     }
1131   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1132     {
1133       if(isAdaptableCorbaPyObject(type,inport->edGetType()))
1134         {
1135           return new PyCorbaStruct(inport);
1136         }
1137       else
1138         {
1139           stringstream msg;
1140           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1141           msg << __FILE__ << ":" <<__LINE__;
1142           throw ConversionException(msg.str());
1143         }
1144     }
1145   // Adaptation not possible
1146   stringstream msg;
1147   msg << "Cannot connect Python output port with type: " << type->id() ;
1148   msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1149 #ifdef _DEVDEBUG_
1150   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1151 #endif
1152   throw ConversionException(msg.str());
1153 }
1154
1155 //! Adapt a CORBA input port to connect it to a XML output port 
1156 /*!
1157  *   \param inport : input port to adapt to Xml type type
1158  *   \param type : type supported by output port
1159  *   \return an adaptator port of type InputXmlPort 
1160  */
1161
1162 InputPort* RuntimeSALOME::adaptCorbaToXml(InputCorbaPort* inport,
1163                                           TypeCode * type) throw (ConversionException)
1164 {
1165   // BEWARE : using the generic check
1166   if(inport->edGetType()->isAdaptable(type))
1167     {
1168       //output type is convertible to input type
1169       return new XmlCorba(inport);
1170     }
1171   //output type is not convertible
1172   stringstream msg;
1173   msg << "Cannot connect Xml output port with type: " << type->id() ;
1174   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1175 #ifdef _DEVDEBUG_
1176   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1177 #endif
1178   throw ConversionException(msg.str());
1179 }
1180
1181 //! Adapt a CORBA input port to a C++ output port 
1182 /*!
1183  *   \param inport : input port to adapt to C++ type type
1184  *   \param type : outport data type 
1185  *   \return an adaptator port of type InputCPPPort 
1186  */
1187
1188 InputPort* RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport,
1189                                           TypeCode * type) throw (ConversionException)
1190 {
1191   DEBTRACE("RuntimeSALOME::adaptCorbaToCpp(InputCorbaPort* inport" );
1192   if(isAdaptableCorbaCpp(type,inport->edGetType()))
1193     {
1194       //output type is convertible to input type
1195       return new CppCorba(inport);
1196     }
1197   //output type is not convertible
1198   stringstream msg;
1199   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1200   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1201 #ifdef _DEVDEBUG_
1202   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1203 #endif
1204   throw ConversionException(msg.str());
1205 }
1206
1207 //! Adapt a CORBA input port to a neutral data 
1208 /*!
1209  *   \param inport : InputPort to adapt to Neutral type type
1210  *   \param type : outport data type 
1211  *   \return an adaptator port of type Neutralxxxx
1212  */
1213
1214 InputPort* RuntimeSALOME::adaptCorbaToNeutral(InputCorbaPort* inport,
1215                                               TypeCode * type) throw (ConversionException)
1216 {
1217   if(inport->edGetType()->kind() == Double)
1218     {
1219       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaDouble(inport);
1220     }
1221   else if(inport->edGetType()->kind() == Int)
1222     {
1223       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaInt(inport);
1224     }
1225   else if(inport->edGetType()->kind() == String)
1226     {
1227       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaString(inport);
1228     }
1229   else if(inport->edGetType()->kind() == Bool)
1230     {
1231       if(isAdaptableCorbaNeutral(type,inport->edGetType()))return new NeutralCorbaBool(inport);
1232     }
1233   else if(inport->edGetType()->kind() == Objref)
1234     {
1235       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaObjref(inport);
1236     }
1237   else if(inport->edGetType()->kind() == Sequence)
1238     {
1239       if(isAdaptableCorbaNeutral(type,inport->edGetType()))
1240         return new NeutralCorbaSequence(inport);
1241       else
1242         {
1243           stringstream msg;
1244           msg << "Cannot convert this sequence type " ;
1245           msg << __FILE__ << ":" <<__LINE__;
1246           throw ConversionException(msg.str());
1247         }
1248     }
1249   else if(inport->edGetType()->kind() == Struct)
1250     {
1251       if(isAdaptableCorbaNeutral(type,inport->edGetType())) return new NeutralCorbaStruct(inport);
1252     }
1253
1254   // Adaptation not possible
1255   stringstream msg;
1256   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1257   msg << " to Corba input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1258 #ifdef _DEVDEBUG_
1259   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1260 #endif
1261   throw ConversionException(msg.str());
1262 }
1263
1264 //! Adapt a CORBA input port to an output which implementation and type are given by impl and type
1265 /*!
1266  *   \param source : input port to adapt to implementation impl and type type
1267  *   \param impl : output port implementation (C++, Python or Corba)
1268  *   \param type : outport data type 
1269  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1270  *   \return an adaptator port which type depends on impl
1271  */
1272
1273 InputPort* RuntimeSALOME::adapt(InputCorbaPort* source,
1274                                 const std::string& impl,
1275                                 TypeCode * type,bool init) throw (ConversionException)
1276 {
1277   if(impl == CppNode::IMPL_NAME)
1278     {
1279       return adaptCorbaToCpp(source,type);
1280     }
1281   else if(impl == PythonNode::IMPL_NAME)
1282     {
1283       return adaptCorbaToPython(source,type);
1284     }
1285   else if(impl == CORBANode::IMPL_NAME)
1286     {
1287       if(init)
1288         return adaptCorbaToCorba(source,type);
1289       else
1290         return adaptCorbaToCorba(source,type);
1291     }
1292   else if(impl == XmlNode::IMPL_NAME )
1293     {
1294       return adaptCorbaToXml(source,type);
1295     }
1296   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1297     {
1298       return adaptCorbaToNeutral(source,type);
1299     }
1300   else
1301     {
1302       stringstream msg;
1303       msg << "Cannot connect InputCorbaPort : unknown implementation " ;
1304       msg << __FILE__ << ":" <<__LINE__;
1305       throw ConversionException(msg.str());
1306     }
1307 }
1308
1309 //! Adapt a Python input port to a Python output port
1310 /*!
1311  * No need to make conversion or cast. 
1312  * Only check, it's possible.
1313  *   \param inport : InputPort to adapt to Python type type
1314  *   \param type : outport data type 
1315  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1316  *   \return an adaptator port of type InputPyPort 
1317  */
1318
1319 InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport,
1320                                               TypeCode * type,bool init) throw (ConversionException)
1321 {
1322   if(init)
1323     return new PyInit(inport);
1324
1325   if(isAdaptablePyObjectPyObject(type,inport->edGetType()))
1326     {
1327       //output data is convertible to input type
1328       //With python, no need to convert. Conversion will be done automatically
1329       //by the interpreter
1330       return new ProxyPort(inport);
1331     }
1332   //output data is not convertible to input type
1333   stringstream msg;
1334   msg << "Cannot connect Python output port with type: " << type->id() ;
1335   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1336 #ifdef _DEVDEBUG_
1337   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1338 #endif
1339   throw ConversionException(msg.str());
1340 }
1341
1342 //! Adapt a Python input port to a C++ output port
1343 /*!
1344  *   \param inport : InputPort to adapt to C++ type type
1345  *   \param type : outport data type 
1346  *   \return an adaptator port of C++ type (InputCppPort)
1347  */
1348
1349 InputPort* RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport,
1350                                            TypeCode * type) throw (ConversionException)
1351 {
1352   DEBTRACE("RuntimeSALOME::adaptPythonToCpp(InputPyPort* inport" );
1353   if(isAdaptablePyObjectCpp(type,inport->edGetType()))
1354     {
1355       //output type is convertible to input type
1356       return new CppPy(inport);
1357     }
1358   //output type is not convertible
1359   stringstream msg;
1360   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1361   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1362 #ifdef _DEVDEBUG_
1363   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1364 #endif
1365   throw ConversionException(msg.str());
1366 }
1367
1368 //! Adapt a Python input port to a Neutral data port
1369 /*!
1370  *   \param inport : InputPort to adapt to Neutral type type
1371  *   \param type : outport data type 
1372  *   \return an adaptator port of Neutral type (Neutralxxxx)
1373  */
1374
1375 InputPort* RuntimeSALOME::adaptPythonToNeutral(InputPyPort* inport,
1376                                                TypeCode * type) throw (ConversionException)
1377 {
1378   if(inport->edGetType()->kind() == Double)
1379     {
1380       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyDouble(inport);
1381     }
1382   else if(inport->edGetType()->kind() == Int)
1383     {
1384       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyInt(inport);
1385     }
1386   else if(inport->edGetType()->kind() == String)
1387     {
1388       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyString(inport);
1389     }
1390   else if(inport->edGetType()->kind() == Bool)
1391     {
1392       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyBool(inport);
1393     }
1394   else if(inport->edGetType()->kind() == Objref)
1395     {
1396       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))return new NeutralPyObjref(inport);
1397     }
1398   else if(inport->edGetType()->kind() == Sequence)
1399     {
1400       if(isAdaptablePyObjectNeutral(type,inport->edGetType()))
1401         return new NeutralPySequence(inport);
1402       else
1403         {
1404           stringstream msg;
1405           msg << "Cannot convert this sequence type " ;
1406           msg << __FILE__ << ":" <<__LINE__;
1407           throw ConversionException(msg.str());
1408         }
1409     }
1410   else if(inport->edGetType()->kind() == Struct)
1411     {
1412       if(isAdaptablePyObjectNeutral(type,inport->edGetType())) return new NeutralPyStruct(inport);
1413     }
1414
1415   // Adaptation not possible
1416   stringstream msg;
1417   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1418   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1419 #ifdef _DEVDEBUG_
1420   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1421 #endif
1422   throw ConversionException(msg.str());
1423 }
1424
1425 //! Adapt a Python input port to a Corba output port
1426 /*!
1427  * Always convert the data
1428  *   \param inport : InputPort to adapt to Corba type type
1429  *   \param type : outport data type 
1430  *   \return an adaptator port of Corba type (InputCorbaPort)
1431  */
1432
1433 InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport,
1434                                              TypeCode * type) throw (ConversionException)
1435 {
1436   if(inport->edGetType()->kind() == Double)
1437     {
1438       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyDouble(inport);
1439     }
1440   else if(inport->edGetType()->kind() == Int)
1441     {
1442       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyInt(inport);
1443     }
1444   else if(inport->edGetType()->kind() == String)
1445     {
1446       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyString(inport);
1447     }
1448   else if(inport->edGetType()->kind() == Bool)
1449     {
1450       if(isAdaptablePyObjectCorba(type,inport->edGetType()))return new CorbaPyBool(inport);
1451     }
1452   else if(inport->edGetType()->kind() == Objref)
1453     {
1454       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1455         {
1456           return new CorbaPyObjref(inport);
1457         }
1458       else
1459         {
1460           stringstream msg;
1461           msg << "Cannot connect InputCorbaPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id();
1462           msg << " " << __FILE__ << ":" <<__LINE__;
1463           throw ConversionException(msg.str());
1464         }
1465     }
1466   else if(inport->edGetType()->kind() == Sequence)
1467     {
1468       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1469         {
1470           return new CorbaPySequence(inport);
1471         }
1472       else
1473         {
1474           stringstream msg;
1475           msg << "Cannot convert this sequence type " ;
1476           msg << __FILE__ << ":" <<__LINE__;
1477           throw ConversionException(msg.str());
1478         }
1479     }
1480   else if(inport->edGetType()->kind() == YACS::ENGINE::Struct)
1481     {
1482       if(isAdaptablePyObjectCorba(type,inport->edGetType()))
1483         {
1484           return new CorbaPyStruct(inport);
1485         }
1486       else
1487         {
1488           stringstream msg;
1489           msg << "Cannot convert this struct type " << type->id() << " to " << inport->edGetType()->id();
1490           msg << " " << __FILE__ << ":" <<__LINE__;
1491           throw ConversionException(msg.str());
1492         }
1493     }
1494   // Adaptation not possible
1495   stringstream msg;
1496   msg << "Cannot connect Corba output port with type: " << type->id() ;
1497   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1498 #ifdef _DEVDEBUG_
1499   msg << " ("__FILE__ << ":" << __LINE__ << ")";
1500 #endif
1501   throw ConversionException(msg.str());
1502 }
1503
1504 //! Adapt a Python input port to a Xml output port 
1505 /*!
1506  *   \param inport : input port to adapt to Xml type type
1507  *   \param type : output port type
1508  *   \return an input port of type InputXmlPort
1509  */
1510
1511 InputPort* RuntimeSALOME::adaptPythonToXml(InputPyPort* inport,
1512                                           TypeCode * type) throw (ConversionException)
1513 {
1514   // BEWARE : using the generic check
1515   if(inport->edGetType()->isAdaptable(type))
1516     {
1517       //convertible type
1518       return new XmlPython(inport);
1519     }
1520   //non convertible type
1521   stringstream msg;
1522   msg << "Cannot connect Xml output port with type: " << type->id() ;
1523   msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1524 #ifdef _DEVDEBUG_
1525   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1526 #endif
1527   throw ConversionException(msg.str());
1528 }
1529
1530 //! Adapt a Python input port to an output port with a given implementation
1531 /*!
1532  *   \param source : input port to adapt to implementation impl and type type
1533  *   \param impl : output port implementation (C++, Python or Corba)
1534  *   \param type : output port type
1535  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1536  *   \return     adaptated input port
1537  */
1538
1539 InputPort* RuntimeSALOME::adapt(InputPyPort* source,
1540                                 const std::string& impl,
1541                                 TypeCode * type,bool init) throw (ConversionException)
1542 {
1543   if(impl == CppNode::IMPL_NAME)
1544     {
1545       return adaptPythonToCpp(source,type);
1546     }
1547   else if(impl == PythonNode::IMPL_NAME)
1548     {
1549       return adaptPythonToPython(source,type,init);
1550     }
1551   else if(impl == CORBANode::IMPL_NAME)
1552     {
1553       return adaptPythonToCorba(source,type);
1554     }
1555   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1556     {
1557       return adaptPythonToNeutral(source,type);
1558     }
1559   else if(impl == XmlNode::IMPL_NAME)
1560     {
1561       return adaptPythonToXml(source,type);
1562     }
1563   else
1564     {
1565       stringstream msg;
1566       msg << "Cannot connect InputPyPort : unknown implementation " << impl;
1567       msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1568       throw ConversionException(msg.str());
1569     }
1570 }
1571
1572
1573 //! Adapt a C++ input port to connect it to a CORBA output port
1574 /*!
1575  *   \param inport : input port to adapt to CORBA type type
1576  *   \param type : type supported by output port
1577  *   \return an adaptator port of type InputCorbaPort
1578  */
1579
1580 InputPort* RuntimeSALOME::adaptCppToCorba(InputCppPort* inport,
1581                                           TypeCode * type) throw (ConversionException)
1582 {
1583   DEBTRACE("RuntimeSALOME::adaptCppToCorba(InputCppPort* inport)");
1584   if(isAdaptableCppCorba(type,inport->edGetType()))
1585     {
1586       //output type is convertible to input type
1587       return new CorbaCpp(inport);
1588     }
1589   //output type is not convertible
1590   stringstream msg;
1591   msg << "Cannot connect Corba output port with type: " << type->id() ;
1592   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1593 #ifdef _DEVDEBUG_
1594   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1595 #endif
1596   throw ConversionException(msg.str());
1597 }
1598
1599 //! Adapt a C++ input port to a Python output port
1600 /*!
1601  *   \param inport : input port to adapt to Python type type
1602  *   \param type : output port type
1603  *   \return an adaptated input port of type InputPyPort
1604  */
1605 InputPort* RuntimeSALOME::adaptCppToPython(InputCppPort* inport,
1606                       TypeCode * type) throw (ConversionException)
1607 {
1608   DEBTRACE("RuntimeSALOME::adaptCppToPython(InputCppPort* inport)");
1609   if(isAdaptableCppPyObject(type,inport->edGetType()))
1610     {
1611       //output type is convertible to input type
1612       return new PyCpp(inport);
1613     }
1614   //output type is not convertible
1615   stringstream msg;
1616   msg << "Cannot connect Python output port with type: " << type->id() ;
1617   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1618 #ifdef _DEVDEBUG_
1619   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1620 #endif
1621   throw ConversionException(msg.str());
1622 }
1623
1624 //! Adapt a C++ input port to a C++ output port
1625 /*!
1626  *   \param inport : input port to adapt to C++ type type
1627  *   \param type : output port type
1628  *   \return an adaptated input port of type InputPyPort
1629  */
1630 InputPort* RuntimeSALOME::adaptCppToCpp(InputCppPort* inport,
1631                       TypeCode * type) throw (ConversionException)
1632 {
1633   DEBTRACE("RuntimeSALOME::adaptCppToCpp(InputPort* inport" );
1634   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1635   if(type->isAdaptable(inport->edGetType()))
1636     {
1637       //the output data is convertible to inport type
1638       return new CppCpp(inport);
1639     }
1640   //non convertible type
1641   stringstream msg;
1642   msg << "Cannot connect Cpp output port with type: " << type->id() ;
1643   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1644 #ifdef _DEVDEBUG_
1645   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1646 #endif
1647   throw ConversionException(msg.str());
1648 }
1649
1650 //! Adapt a C++ input port to a Neutral output port
1651 /*!
1652  *   \param inport : input port to adapt to C++ type type
1653  *   \param type : output port type
1654  *   \return an adaptated input port of type InputPyPort
1655  */
1656 InputPort* RuntimeSALOME::adaptCppToNeutral(InputCppPort* inport,
1657                       TypeCode * type) throw (ConversionException)
1658 {
1659   DEBTRACE("RuntimeSALOME::adaptCppToNeutral(InputPort* inport" );
1660   DEBTRACE(type->kind() << "   " << inport->edGetType()->kind() );
1661   if(type->isAdaptable(inport->edGetType()))
1662     {
1663       //the output data is convertible to inport type
1664       return new NeutralCpp(inport);
1665     }
1666   //non convertible type
1667   stringstream msg;
1668   msg << "Cannot connect Neutral output port with type: " << type->id() ;
1669   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1670 #ifdef _DEVDEBUG_
1671   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1672 #endif
1673   throw ConversionException(msg.str());
1674 }
1675
1676 InputPort* RuntimeSALOME::adaptCppToXml(InputCppPort* inport,
1677                       TypeCode * type) throw (ConversionException)
1678 {
1679   DEBTRACE("RuntimeSALOME::adaptCppToXml(InputCppPort* inport" );
1680   if(isAdaptableCppXml(type,inport->edGetType()))
1681     {
1682       //convertible type
1683       return new XmlCpp(inport);
1684     }
1685   //non convertible type
1686   stringstream msg;
1687   msg << "Cannot connect Xml output port with type: " << type->id() ;
1688   msg << " to Cpp input port " << inport->getName() << " with type: " << inport->edGetType()->id();
1689 #ifdef _DEVDEBUG_
1690   msg <<  " ("<<__FILE__ << ":" << __LINE__<<")";
1691 #endif
1692    throw ConversionException(msg.str());
1693 }
1694
1695 //! Adapt a C++ input port to connect it to an output port with a given implementation
1696 /*!
1697  *   \param source : input port to adapt to implementation impl and type type
1698  *   \param impl : output port implementation (C++, Python or Corba)
1699  *   \param type : output port supported type
1700  *   \param init : if init is true the proxy port will be used in initialization of input port (needs value check)
1701  *   \return       the adaptated port
1702  */
1703
1704 InputPort* RuntimeSALOME::adapt(InputCppPort* source,
1705                                 const std::string& impl,
1706                                 TypeCode * type,bool init) throw (ConversionException)
1707 {
1708   DEBTRACE("RuntimeSALOME::adapt(InputCppPort* source)");
1709   if(impl == CORBANode::IMPL_NAME)
1710     {
1711       return adaptCppToCorba(source,type);
1712     }
1713   else if(impl == PythonNode::IMPL_NAME)
1714     {
1715       return adaptCppToPython(source,type);
1716     }
1717   else if(impl == XmlNode::IMPL_NAME)
1718     {
1719       return adaptCppToXml(source,type);
1720     }
1721   else if(impl == CppNode::IMPL_NAME)
1722     {
1723       return adaptCppToCpp(source, type);
1724     }
1725   else if(impl == Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
1726     {
1727       return adaptCppToNeutral(source, type);
1728     }
1729   else
1730     {
1731       stringstream msg;
1732       msg << "Cannot connect InputCppPort to " << impl << " implementation";
1733       msg << " ("__FILE__ << ":" << __LINE__ << ")";
1734       throw ConversionException(msg.str());
1735     }
1736 }
1737
1738 // bool RuntimeSALOME::isCompatible(const OutputPort* outputPort, 
1739 //                               const InputPort*  inputPort)
1740 // {
1741 //   bool result=true;
1742 //   return result;
1743 // }
1744
1745 CORBA::ORB_ptr RuntimeSALOME::getOrb()
1746 {
1747   return _orb;
1748 }
1749
1750 PyObject * RuntimeSALOME::getPyOrb()
1751 {
1752   return _pyorb;
1753 }
1754
1755 PyObject * RuntimeSALOME::getBuiltins()
1756 {
1757   return _bltins;
1758 }
1759
1760 DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory()
1761 {
1762   return _dynFactory;
1763 }
1764
1765 PyObject * RuntimeSALOME::get_omnipy()
1766 {
1767   return _omnipy;
1768 }
1769
1770 omniORBpyAPI* RuntimeSALOME::getApi()
1771 {
1772   return _api;
1773 }
1774
1775 void* RuntimeSALOME::convertNeutral(TypeCode * type, Any *data)
1776 {
1777   if(data)
1778     return (void *)convertNeutralPyObject(type,data);
1779   else
1780     {
1781       Py_INCREF(Py_None);
1782       return (void *)Py_None;
1783     }
1784 }
1785
1786 std::string RuntimeSALOME::convertNeutralAsString(TypeCode * type, Any *data)
1787 {
1788   PyObject* ob;
1789   if(data)
1790     {
1791       ob=convertNeutralPyObject(type,data);
1792       std::string s=convertPyObjectToString(ob);
1793
1794       // Note (Renaud Barate, 8 jan 2013): With Python 2.7, this call to Py_DECREF causes a crash
1795       // (SIGSEGV) when ob is a sequence and the call is not protected with the global interpreter
1796       // lock. I thus added the call to PyGILState_Ensure / PyGILState_Release. It worked fine in
1797       // Python 2.6 without this call. If anyone finds the real reason of this bug and another fix,
1798       // feel free to change this code.
1799       PyGILState_STATE gstate = PyGILState_Ensure();
1800       Py_DECREF(ob);
1801       PyGILState_Release(gstate);
1802       return s;
1803     }
1804   else
1805     {
1806       return "None";
1807     }
1808 }
1809
1810 std::string RuntimeSALOME::convertPyObjectToString(PyObject* ob)
1811 {
1812   return YACS::ENGINE::convertPyObjectToString(ob);
1813 }
1814
1815 PyObject* RuntimeSALOME::convertStringToPyObject(const std::string& s)
1816 {
1817   PyObject *mainmod;
1818   PyObject *globals;
1819   PyObject* ob;
1820   PyGILState_STATE gstate = PyGILState_Ensure();
1821   mainmod = PyImport_AddModule("__main__");
1822   globals = PyModule_GetDict(mainmod);
1823   PyObject* d = PyDict_New();
1824   //PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins());
1825   ob= PyRun_String( s.c_str(), Py_eval_input, globals, d);
1826   Py_DECREF(d);
1827   if(ob==NULL)
1828     {
1829       //exception
1830       std::string error;
1831       PyObject* new_stderr = newPyStdOut(error);
1832       PySys_SetObject((char *)"stderr", new_stderr);
1833       PyErr_Print();
1834       PySys_SetObject((char *)"stderr", PySys_GetObject((char *)"__stderr__"));
1835       Py_DECREF(new_stderr);
1836       PyGILState_Release(gstate);
1837       throw Exception(error);
1838     }
1839   PyGILState_Release(gstate);
1840   return ob;
1841 }