Salome HOME
CCAR: add the PyNode object that can be created in a container
[modules/kernel.git] / src / Container / Container_i.cxx
index 41e2b5b61ab952a652a7f01ce896b388e41a39b7..f7124ac82ba1074dd5e62579b0db86329bf985ff 100644 (file)
@@ -1,53 +1,49 @@
-//  SALOME Container : implementation of container and engine for Kernel
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
 //
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+//  SALOME Container : implementation of container and engine for Kernel
 //  File   : Container_i.cxx
 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA 
 //  Module : SALOME
 //  $Header$
-
 //#define private public
+//
 #include <string.h>
 #include <stdio.h>
 #include <time.h>
-#ifndef WNT
+#ifndef WIN32
 #include <sys/time.h>
 #include <dlfcn.h>
 #include <unistd.h>
 #else
 #include <signal.h>
 #include <process.h>
+#include <direct.h>
 int SIGUSR1 = 1000;
 #endif
 
 #include "utilities.h"
 #include <SALOMEconfig.h>
-//#ifndef WNT
 #include CORBA_SERVER_HEADER(SALOME_Component)
 #include CORBA_SERVER_HEADER(SALOME_Exception)
-//#else
-//#include <SALOME_Component.hh>
-//#endif
 #include <pthread.h>  // must be before Python.h !
 #include "SALOME_Container_i.hxx"
 #include "SALOME_Component_i.hxx"
@@ -55,7 +51,7 @@ int SIGUSR1 = 1000;
 #include "SALOME_FileTransfer_i.hxx"
 #include "Salome_file_i.hxx"
 #include "SALOME_NamingService.hxx"
-#include "OpUtil.hxx"
+#include "Basics_Utils.hxx"
 
 #include <Python.h>
 #include "Container_init_python.hxx"
@@ -68,15 +64,17 @@ bool _Sleeping = false ;
 int _ArgC ;
 char ** _ArgV ;
 
-
-// Containers with name FactoryServer are started via rsh in LifeCycleCORBA
-// Other Containers are started via start_impl of FactoryServer
-
 extern "C" {void ActSigIntHandler() ; }
-#ifndef WNT
-  extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
+#ifndef WIN32
+extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
+#else
+extern "C" {void SigIntHandler( int ) ; }
+#endif
+
+#ifdef WIN32
+# define separator '\\'
 #else
-  extern "C" {void SigIntHandler( int ) ; }
+# define separator '/'
 #endif
 
 
@@ -85,21 +83,32 @@ map<std::string, void *> Engines_Container_i::_library_map;
 map<std::string, void *> Engines_Container_i::_toRemove_map;
 omni_mutex Engines_Container_i::_numInstanceMutex ;
 
+static PyObject* _pyCont;
+
+int checkifexecutable(const std::string&);
+int findpathof(std::string&, const std::string&);
+
+/*! \class Engines_Container_i
+ *  \brief C++ implementation of Engines::Container interface
+ *
+ */
+
+
 //=============================================================================
 /*! 
- *  Default constructor, not for use
- */
+*  Default constructor, not for use
+*/
 //=============================================================================
 
 Engines_Container_i::Engines_Container_i () :
-  _numInstance(0)
+_numInstance(0),_id(0),_NS(0)
 {
 }
 
 //=============================================================================
 /*! 
- *  Construtor to use
- */
+*  Construtor to use
+*/
 //=============================================================================
 
 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, 
@@ -109,7 +118,7 @@ Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
                                           bool activAndRegist,
                                           bool isServantAloneInProcess
                                           ) :
-  _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
+  _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess),_id(0),_NS(0)
 {
   _pid = (long)getpid();
 
@@ -119,132 +128,132 @@ Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
   _argc = argc ;
   _argv = argv ;
 
-  string hostname = GetHostname();
-#ifndef WNT
+  string hostname = Kernel_Utils::GetHostname();
+#ifndef WIN32
   MESSAGE(hostname << " " << getpid() << 
-         " Engines_Container_i starting argc " <<
-   _argc << " Thread " << pthread_self() ) ;
+    " Engines_Container_i starting argc " <<
+    _argc << " Thread " << pthread_self() ) ;
 #else
   MESSAGE(hostname << " " << _getpid() << 
-         " Engines_Container_i starting argc " << _argc<< " Thread " << pthread_self().p ) ;
+    " Engines_Container_i starting argc " << _argc<< " Thread " << pthread_self().p ) ;
 #endif
 
   int i = 0 ;
   while ( _argv[ i ] )
-    {
-      MESSAGE("           argv" << i << " " << _argv[ i ]) ;
-      i++ ;
-    }
+  {
+    MESSAGE("           argv" << i << " " << _argv[ i ]) ;
+    i++ ;
+  }
 
   if ( argc < 2 )
-    {
-      INFOS("SALOME_Container usage : SALOME_Container ServerName");
-      ASSERT(0) ;
-    }
+  {
+    INFOS("SALOME_Container usage : SALOME_Container ServerName");
+    ASSERT(0) ;
+  }
   SCRUTE(argv[1]);
   _isSupervContainer = false;
   if (strcmp(argv[1],"SuperVisionContainer") == 0) _isSupervContainer = true;
 
   if (_isSupervContainer)
-    {
-      _ArgC = argc ;
-      _ArgV = argv ;
-    }
+  {
+    _ArgC = argc ;
+    _ArgV = argv ;
+  }
 
   _orb = CORBA::ORB::_duplicate(orb) ;
   _poa = PortableServer::POA::_duplicate(poa) ;
-  
+
   // Pour les containers paralleles: il ne faut pas enregistrer et activer
   // le container generique, mais le container specialise
 
   if(activAndRegist)
+  {
+    _id = _poa->activate_object(this);
+    _NS = new SALOME_NamingService();
+    _NS->init_orb( _orb ) ;
+    CORBA::Object_var obj=_poa->id_to_reference(*_id);
+    Engines::Container_var pCont 
+      = Engines::Container::_narrow(obj);
+    _remove_ref();
+
+    _containerName = _NS->BuildContainerNameForNS(containerName,
+      hostname.c_str());
+    SCRUTE(_containerName);
+    _NS->Register(pCont, _containerName.c_str());
+    MESSAGE("Engines_Container_i::Engines_Container_i : Container name "
+      << _containerName);
+
+    // Python: 
+    // import SALOME_Container
+    // pycont = SALOME_Container.SALOME_Container_i(containerIORStr)
+
+    CORBA::String_var sior =  _orb->object_to_string(pCont);
+    string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
+    myCommand += _containerName + "','";
+    myCommand += sior;
+    myCommand += "')\n";
+    SCRUTE(myCommand);
+
+    if (!_isSupervContainer)
     {
-      _id = _poa->activate_object(this);
-      _NS = new SALOME_NamingService();
-      _NS->init_orb( _orb ) ;
-      CORBA::Object_var obj=_poa->id_to_reference(*_id);
-      Engines::Container_var pCont 
-        = Engines::Container::_narrow(obj);
-      _remove_ref();
-
-      _containerName = _NS->BuildContainerNameForNS(containerName,
-                                                    hostname.c_str());
-      SCRUTE(_containerName);
-      _NS->Register(pCont, _containerName.c_str());
-      MESSAGE("Engines_Container_i::Engines_Container_i : Container name "
-              << _containerName);
-
-      // Python: 
-      // import SALOME_Container
-      // pycont = SALOME_Container.SALOME_Container_i(containerIORStr)
-    
-      CORBA::String_var sior =  _orb->object_to_string(pCont);
-      string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
-      myCommand += _containerName + "','";
-      myCommand += sior;
-      myCommand += "')\n";
-      SCRUTE(myCommand);
-
-      if (!_isSupervContainer)
-        {
-#ifdef WNT
-
-          PyEval_AcquireLock();
-          PyThreadState *myTstate = PyThreadState_New(KERNEL_PYTHON::_interp);
-          PyThreadState *myoldTstate = PyThreadState_Swap(myTstate);
-#else
-          Py_ACQUIRE_NEW_THREAD;
+      PyGILState_STATE gstate = PyGILState_Ensure();
+
+#ifdef WIN32
+      // mpv: this is temporary solution: there is a unregular crash if not
+      //Sleep(2000);
+      //
+      // first element is the path to Registry.dll, but it's wrong
+      PyRun_SimpleString("import sys\n");
+      PyRun_SimpleString("sys.path = sys.path[1:]\n");
 #endif
+      PyRun_SimpleString("import SALOME_Container\n");
+      PyRun_SimpleString((char*)myCommand.c_str());
+      PyObject *mainmod = PyImport_AddModule("__main__");
+      PyObject *globals = PyModule_GetDict(mainmod);
+      _pyCont = PyDict_GetItemString(globals, "pyCont");
 
-#ifdef WNT
-          // mpv: this is temporary solution: there is a unregular crash if not
-          //Sleep(2000);
-          //
-    // first element is the path to Registry.dll, but it's wrong
-          PyRun_SimpleString("import sys\n");
-          PyRun_SimpleString("sys.path = sys.path[1:]\n");
-#endif
-          PyRun_SimpleString("import SALOME_Container\n");
-          PyRun_SimpleString((char*)myCommand.c_str());
-          Py_RELEASE_NEW_THREAD;
-        }
-
-      fileTransfer_i* aFileTransfer = new fileTransfer_i();
-      CORBA::Object_var obref=aFileTransfer->_this();
-      _fileTransfer = Engines::fileTransfer::_narrow(obref);
-      aFileTransfer->_remove_ref();
+      PyGILState_Release(gstate);
     }
+
+    fileTransfer_i* aFileTransfer = new fileTransfer_i();
+    CORBA::Object_var obref=aFileTransfer->_this();
+    _fileTransfer = Engines::fileTransfer::_narrow(obref);
+    aFileTransfer->_remove_ref();
+  }
 }
 
 //=============================================================================
 /*! 
- *  Destructor
- */
+*  Destructor
+*/
 //=============================================================================
 
 Engines_Container_i::~Engines_Container_i()
 {
   MESSAGE("Container_i::~Container_i()");
-  delete _id;
+  if(_id)
+    delete _id;
   if(_NS)
     delete _NS;
 }
 
 //=============================================================================
+//! Get container name
 /*! 
- *  CORBA attribute: Container name (see constructor)
- */
+*  CORBA attribute: Container name (see constructor)
+*/
 //=============================================================================
 
 char* Engines_Container_i::name()
 {
-   return CORBA::string_dup(_containerName.c_str()) ;
+  return CORBA::string_dup(_containerName.c_str()) ;
 }
 
 //=============================================================================
+//! Get container working directory
 /*! 
- *  CORBA attribute: Container working directory 
- */
+*  CORBA attribute: Container working directory 
+*/
 //=============================================================================
 
 char* Engines_Container_i::workingdir()
@@ -255,9 +264,10 @@ char* Engines_Container_i::workingdir()
 }
 
 //=============================================================================
+//! Get container log file name
 /*! 
- *  CORBA attribute: Container log file name
- */
+*  CORBA attribute: Container log file name
+*/
 //=============================================================================
 
 char* Engines_Container_i::logfilename()
@@ -265,28 +275,31 @@ char* Engines_Container_i::logfilename()
   return CORBA::string_dup(_logfilename.c_str()) ;
 }
 
+//! Set container log file name
 void Engines_Container_i::logfilename(const char* name)
 {
   _logfilename=name;
 }
 
 //=============================================================================
+//! Get container host name
 /*! 
- *  CORBA method: Get the hostName of the Container (without domain extensions)
- */
+*  CORBA method: Get the hostName of the Container (without domain extensions)
+*/
 //=============================================================================
 
 char* Engines_Container_i::getHostName()
 {
-  string s = GetHostname();
+  string s = Kernel_Utils::GetHostname();
   //  MESSAGE("Engines_Container_i::getHostName " << s);
   return CORBA::string_dup(s.c_str()) ;
 }
 
 //=============================================================================
+//! Get container PID
 /*! 
- *  CORBA method: Get the PID (process identification) of the Container
- */
+*  CORBA method: Get the PID (process identification) of the Container
+*/
 //=============================================================================
 
 CORBA::Long Engines_Container_i::getPID()
@@ -295,9 +308,10 @@ CORBA::Long Engines_Container_i::getPID()
 }
 
 //=============================================================================
+//! Ping the servant to check it is still alive
 /*! 
- *  CORBA method: check if servant is still alive
- */
+*  CORBA method: check if servant is still alive
+*/
 //=============================================================================
 
 void Engines_Container_i::ping()
@@ -306,12 +320,13 @@ void Engines_Container_i::ping()
 }
 
 //=============================================================================
+//! Shutdown the container
 /*! 
- *  CORBA method, oneway: Server shutdown. 
- *  - Container name removed from naming service,
- *  - servant deactivation,
- *  - orb shutdown if no other servants in the process 
- */
+*  CORBA method, oneway: Server shutdown. 
+*  - Container name removed from naming service,
+*  - servant deactivation,
+*  - orb shutdown if no other servants in the process 
+*/
 //=============================================================================
 
 void Engines_Container_i::Shutdown()
@@ -319,33 +334,165 @@ void Engines_Container_i::Shutdown()
   MESSAGE("Engines_Container_i::Shutdown()");
 
   /* For each component contained in this container
-   * tell it to self-destroy
-   */
+  * tell it to self-destroy
+  */
   std::map<std::string, Engines::Component_var>::iterator itm;
   for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
-    itm->second->destroy();
+    {
+      try
+        {
+          itm->second->destroy();
+        }
+      catch(const CORBA::Exception& e)
+        {
+          // ignore this entry and continue
+        }
+      catch(...)
+        {
+          // ignore this entry and continue
+        }
+    }
+  _listInstances_map.clear();
 
   _NS->Destroy_FullDirectory(_containerName.c_str());
   _NS->Destroy_Name(_containerName.c_str());
-  //_remove_ref();
-  //_poa->deactivate_object(*_id);
   if(_isServantAloneInProcess)
+  {
+    MESSAGE("Effective Shutdown of container Begins...");
+    if(!CORBA::is_nil(_orb))
+      _orb->shutdown(0);
+  }
+}
+
+/* int checkifexecutable(const char *filename)
+* 
+* Return non-zero if the name is an executable file, and
+* zero if it is not executable, or if it does not exist.
+*/
+
+int checkifexecutable(const string& filename)
+{
+  int result;
+  struct stat statinfo;
+
+  result = stat(filename.c_str(), &statinfo);
+  if (result < 0) return 0;
+  if (!S_ISREG(statinfo.st_mode)) return 0;
+
+#ifdef WIN32
+  return 1;
+#else
+  if (statinfo.st_uid == geteuid()) return statinfo.st_mode & S_IXUSR;
+  if (statinfo.st_gid == getegid()) return statinfo.st_mode & S_IXGRP;
+  return statinfo.st_mode & S_IXOTH;
+#endif
+}
+
+
+/* int findpathof(char *pth, const char *exe)
+*
+* Find executable by searching the PATH environment variable.
+*
+* const char *exe - executable name to search for.
+*       char *pth - the path found is stored here, space
+*                   needs to be available.
+*
+* If a path is found, returns non-zero, and the path is stored
+* in pth.  If exe is not found returns 0, with pth undefined.
+*/
+
+int findpathof(string& pth, const string& exe)
+{
+  string path( getenv("PATH") );
+  if ( path.size() == 0 )
+         return 0;
+       
+  char path_spr =
+#ifdef WIN32
+                  ';';
+#else
+                  ':';
+#endif
+
+    char dir_spr = 
+#ifdef WIN32
+                  '\\';
+#else
+                  '/';
+#endif
+    
+  int offset = 0;
+  int stop = 0;
+  int found = 0;
+  while(!stop && !found)
+  {
+    int pos = path.find( path_spr, offset );
+    if (pos == string::npos)
+      stop = 1;
+
+    pth = path.substr( offset, pos - offset );
+    if ( pth.size() > 0 )
     {
-      MESSAGE("Effective Shutdown of container Begins...");
-      if(!CORBA::is_nil(_orb))
-       _orb->shutdown(0);
+      if( pth[pth.size()-1] != dir_spr )
+        pth += dir_spr;
+      pth += exe;
+      found = checkifexecutable(pth.c_str());
     }
+    offset = pos+1;
+  }
+
+
+/*  char *searchpath;
+  char *beg, *end;
+  int stop, found;
+  int len;
+
+  if (strchr(exe, separator) != NULL) {
+#ifndef WIN32
+    if (realpath(exe, pth) == NULL) return 0;
+#endif
+    return  checkifexecutable(pth);
+  }
+
+  searchpath = getenv("PATH");
+  if (searchpath == NULL) return 0;
+  if (strlen(searchpath) <= 0) return 0;
+
+  string env_path(searchpath);
+
+  beg = searchpath;
+  stop = 0; found = 0;
+  do {
+    end = strchr(beg, ':');
+    if (end == NULL) {
+      stop = 1;
+      strncpy(pth, beg, PATH_MAX);
+      len = strlen(pth);
+    } else {
+      strncpy(pth, beg, end - beg);
+      pth[end - beg] = '\0';
+      len = end - beg;
+    }
+    if (pth[len - 1] != '/') strncat(pth, "/", 1);
+    strncat(pth, exe, PATH_MAX - len);
+    found = checkifexecutable(pth);
+    if (!stop) beg = end + 1;
+  } while (!stop && !found);
+*/
+  return found;
 }
 
 
+
 //=============================================================================
+//! load a new component class
 /*! 
- *  CORBA method: load a new component class (Python or C++ implementation)
- *  \param componentName like COMPONENT
- *                          try to make a Python import of COMPONENT,
- *                          then a lib open of libCOMPONENTEngine.so
- *  \return true if dlopen successfull or already done, false otherwise
- */
+*  CORBA method: load a new component class (Python or C++ implementation)
+*  \param componentName like COMPONENT
+*                          try to make a Python import of COMPONENT,
+*                          then a lib open of libCOMPONENTEngine.so
+*  \return true if dlopen successfull or already done, false otherwise
+*/
 //=============================================================================
 
 bool
@@ -356,26 +503,28 @@ Engines_Container_i::load_component_Library(const char* componentName)
 
   // --- try dlopen C++ component
 
-#ifndef WNT
+#ifndef WIN32
   string impl_name = string ("lib") + aCompName + string("Engine.so");
 #else
   string impl_name = aCompName + string("Engine.dll");
 #endif
   SCRUTE(impl_name);
-  
+
   _numInstanceMutex.lock(); // lock to be alone 
   // (see decInstanceCnt, finalize_removal))
   if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name);
   if (_library_map.count(impl_name) != 0)
-    {
-      MESSAGE("Library " << impl_name << " already loaded");
-      _numInstanceMutex.unlock();
-      return true;
-    }
-  
-#ifndef WNT
+  {
+    MESSAGE("Library " << impl_name << " already loaded");
+    _numInstanceMutex.unlock();
+    return true;
+  }
+
+  std::string retso="";
+#ifndef WIN32
   void* handle;
   handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
+  if ( !handle )retso=dlerror();
 #else
   HINSTANCE handle;
   handle = LoadLibrary( impl_name.c_str() );
@@ -383,63 +532,72 @@ Engines_Container_i::load_component_Library(const char* componentName)
 
   if ( handle )
   {
-      _library_map[impl_name] = handle;
-      _numInstanceMutex.unlock();
-      return true;
+    _library_map[impl_name] = handle;
+    _numInstanceMutex.unlock();
+    return true;
   }
   _numInstanceMutex.unlock();
 
   // --- try import Python component
 
   INFOS("try import Python component "<<componentName);
+  std::string retpy;
   if (_isSupervContainer)
-    {
-      INFOS("Supervision Container does not support Python Component Engines");
-      return false;
-    }
+  {
+    INFOS("Supervision Container does not support Python Component Engines");
+    return false;
+  }
   if (_library_map.count(aCompName) != 0)
-    {
-      return true; // Python Component, already imported
-    }
+  {
+    return true; // Python Component, already imported
+  }
   else
+  {
+    PyGILState_STATE gstate = PyGILState_Ensure(); 
+    PyObject *result = PyObject_CallMethod(_pyCont,
+      (char*)"import_component",
+      (char*)"s",componentName);
+
+    retpy=PyString_AsString(result);
+    Py_XDECREF(result);
+    SCRUTE(retpy);
+    PyGILState_Release(gstate);
+
+    if (retpy=="") // import possible: Python component
     {
-      Py_ACQUIRE_NEW_THREAD;
-      PyObject *mainmod = PyImport_AddModule("__main__");
-      PyObject *globals = PyModule_GetDict(mainmod);
-      PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
-      PyObject *result = PyObject_CallMethod(pyCont,
-                                             "import_component",
-                                             "s",componentName);
-      int ret= PyInt_AsLong(result);
-      Py_XDECREF(result);
-      SCRUTE(ret);
-      Py_RELEASE_NEW_THREAD;
-  
-      if (ret) // import possible: Python component
-        {
-          _numInstanceMutex.lock() ; // lock to be alone (stl container write)
-          _library_map[aCompName] = (void *)pyCont; // any non O value OK
-          _numInstanceMutex.unlock() ;
-          MESSAGE("import Python: "<<aCompName<<" OK");
-          return true;
-        }
+      _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+      _library_map[aCompName] = (void *)_pyCont; // any non O value OK
+      _numInstanceMutex.unlock() ;
+      MESSAGE("import Python: "<<aCompName<<" OK");
+      return true;
     }
+  }
+  // Try to find an executable
+  std::string executable=aCompName+".exe";
+  string path;
+  if (findpathof(path, executable)) 
+    return true;
+
   INFOS( "Impossible to load component: " << componentName );
   INFOS( "Can't load shared library: " << impl_name );
+  std::cerr << retso << std::endl;
   INFOS( "Can't import Python module: " << componentName );
+  std::cerr << retpy << std::endl;
+  INFOS( "Can't execute program: " << executable );
   return false;
 }
 
 //=============================================================================
+//! Create a new component instance
 /*! 
- *  CORBA method: Creates a new servant instance of a component.
- *  The servant registers itself to naming service and Registry.
- *  \param genericRegisterName  Name of the component instance to register
- *                         in Registry & Name Service (without _inst_n suffix)
- *  \param studyId         0 for multiStudy instance, 
- *                         study Id (>0) otherwise
- *  \return a loaded component
- */
+*  CORBA method: Creates a new servant instance of a component.
+*  The servant registers itself to naming service and Registry.
+*  \param genericRegisterName  Name of the component instance to register
+*                         in Registry & Name Service (without _inst_n suffix)
+*  \param studyId         0 for multiStudy instance, 
+*                         study Id (>0) otherwise
+*  \return a loaded component
+*/
 //=============================================================================
 
 Engines::Component_ptr
@@ -447,129 +605,219 @@ Engines_Container_i::create_component_instance(const char*genericRegisterName,
                                                CORBA::Long studyId)
 {
   if (studyId < 0)
-    {
-      INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
-      return Engines::Component::_nil() ;
-    }
+  {
+    INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
+    return Engines::Component::_nil() ;
+  }
 
   Engines::Component_var iobject = Engines::Component::_nil() ;
 
   string aCompName = genericRegisterName;
   if (_library_map.count(aCompName) != 0) // Python component
+  {
+    if (_isSupervContainer)
     {
-      if (_isSupervContainer)
-        {
-          INFOS("Supervision Container does not support Python Component Engines");
-          return Engines::Component::_nil();
-        }
-      _numInstanceMutex.lock() ; // lock on the instance number
-      _numInstance++ ;
-      int numInstance = _numInstance ;
-      _numInstanceMutex.unlock() ;
-
-      char aNumI[12];
-      sprintf( aNumI , "%d" , numInstance ) ;
-      string instanceName = aCompName + "_inst_" + aNumI ;
-      string component_registerName =
-        _containerName + "/" + instanceName;
-
-      Py_ACQUIRE_NEW_THREAD;
-      PyObject *mainmod = PyImport_AddModule("__main__");
-      PyObject *globals = PyModule_GetDict(mainmod);
-      PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
-      PyObject *result = PyObject_CallMethod(pyCont,
-                                             "create_component_instance",
-                                             "ssl",
-                                             aCompName.c_str(),
-                                             instanceName.c_str(),
-                                             studyId);
-      string iors = PyString_AsString(result);
-      Py_DECREF(result);
-      SCRUTE(iors);
-      Py_RELEASE_NEW_THREAD;
-  
-      if( iors!="" )
-      {
-        CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
-        iobject = Engines::Component::_narrow( obj ) ;
-        _listInstances_map[instanceName] = iobject;
-      }
-      return iobject._retn();
+      INFOS("Supervision Container does not support Python Component Engines");
+      return Engines::Component::_nil();
+    }
+    _numInstanceMutex.lock() ; // lock on the instance number
+    _numInstance++ ;
+    int numInstance = _numInstance ;
+    _numInstanceMutex.unlock() ;
+
+    char aNumI[12];
+    sprintf( aNumI , "%d" , numInstance ) ;
+    string instanceName = aCompName + "_inst_" + aNumI ;
+    string component_registerName =
+      _containerName + "/" + instanceName;
+
+    PyGILState_STATE gstate = PyGILState_Ensure(); 
+    PyObject *result = PyObject_CallMethod(_pyCont,
+      (char*)"create_component_instance",
+      (char*)"ssl",
+      aCompName.c_str(),
+      instanceName.c_str(),
+      studyId);
+    string iors = PyString_AsString(result);
+    Py_DECREF(result);
+    SCRUTE(iors);
+    PyGILState_Release(gstate);
+
+    if( iors!="" )
+    {
+      CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
+      iobject = Engines::Component::_narrow( obj ) ;
+      _listInstances_map[instanceName] = iobject;
     }
-  
+    return iobject._retn();
+  }
+
   //--- try C++
 
-#ifndef WNT
+#ifndef WIN32
   string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
 #else
   string impl_name = genericRegisterName +string("Engine.dll");
 #endif
-  if (_library_map.count(impl_name) == 0) 
+  if (_library_map.count(impl_name) != 0) // C++ component
+  {
+    void* handle = _library_map[impl_name];
+    iobject = createInstance(genericRegisterName,
+      handle,
+      studyId);
+    return iobject._retn();
+  }
+
+  // If it's not a Python or a C++ component try to launch a standalone component
+  // in a sub directory
+  // This component is implemented in an executable with name genericRegisterName.exe
+  // It must register itself in Naming Service. The container waits some time (10 s max)
+  // it's registration.
+
+  _numInstanceMutex.lock() ; // lock on the instance number
+  _numInstance++ ;
+  int numInstance = _numInstance ;
+  _numInstanceMutex.unlock() ;
+
+  char aNumI[12];
+  sprintf( aNumI , "%d" , numInstance ) ;
+  string instanceName = aCompName + "_inst_" + aNumI ;
+  string component_registerName = _containerName + "/" + instanceName;
+
+  //check if an entry exist in naming service
+  CORBA::Object_var nsobj = _NS->Resolve(component_registerName.c_str());
+  if ( !CORBA::is_nil(nsobj) )
+  {
+    // unregister the registered component
+    _NS->Destroy_Name(component_registerName.c_str());
+    //kill or shutdown it ???
+  }
+
+  // first arg container ior string
+  // second arg container name
+  // third arg instance name
+
+  Engines::Container_var pCont= _this();
+  CORBA::String_var sior =  _orb->object_to_string(pCont);
+
+  std::string command;
+  command="mkdir -p ";
+  command+=instanceName;
+  command+=";cd ";
+  command+=instanceName;
+  command+=";";
+  command+=genericRegisterName ;
+  command+=".exe";
+  command+=" ";
+  command+= sior; // container ior string
+  command+=" ";
+  command+=_containerName; //container name
+  command+=" ";
+  command+=instanceName; //instance name
+  command+=" &";
+  MESSAGE("SALOME_Container::create_component_instance command=" << command);
+  // launch component with a system call
+  int status=system(command.c_str());
+
+  if (status == -1)
+  {
+    MESSAGE("SALOME_Container::create_component_instance system failed " << "(system command status -1)");
+    return Engines::Component::_nil();
+  }
+#ifndef WIN32
+  else if (WEXITSTATUS(status) == 217)
+  {
+    MESSAGE("SALOME_Container::create_component_instance system failed " << "(system command status 217)");
+    return Engines::Component::_nil();
+  }
+#endif
+  else
+  {
+    int count=20;
+    CORBA::Object_var obj = CORBA::Object::_nil() ;
+    while ( CORBA::is_nil(obj) && count )
+    {
+#ifndef WIN32
+      sleep( 1 ) ;
+#else
+      Sleep(1000);
+#endif
+      count-- ;
+      MESSAGE( count << ". Waiting for component " << genericRegisterName);
+      obj = _NS->Resolve(component_registerName.c_str());
+    }
+
+    if(CORBA::is_nil(obj))
     {
-      INFOS("shared library " << impl_name <<" must be loaded before creating instance");
-      return Engines::Component::_nil() ;
+      MESSAGE("SALOME_Container::create_component_instance failed");
+      return Engines::Component::_nil();
     }
-  else
+    else
     {
-      void* handle = _library_map[impl_name];
-      iobject = createInstance(genericRegisterName,
-                               handle,
-                               studyId);
+      MESSAGE("SALOME_Container::create_component_instance successful");
+      iobject=Engines::Component::_narrow(obj);
+      _listInstances_map[instanceName] = iobject;
       return iobject._retn();
     }
+  }
 }
 
 //=============================================================================
+//! Find an existing (in the container) component instance
 /*! 
- *  CORBA method: Finds a servant instance of a component
- *  \param registeredName  Name of the component in Registry or Name Service,
- *                         without instance suffix number
- *  \param studyId         0 if instance is not associated to a study, 
- *                         >0 otherwise (== study id)
- *  \return the first instance found with same studyId
- */
+*  CORBA method: Finds a servant instance of a component
+*  \param registeredName  Name of the component in Registry or Name Service,
+*                         without instance suffix number
+*  \param studyId         0 if instance is not associated to a study, 
+*                         >0 otherwise (== study id)
+*  \return the first instance found with same studyId
+*/
 //=============================================================================
 
 Engines::Component_ptr
 Engines_Container_i::find_component_instance( const char* registeredName,
-                                              CORBA::Long studyId)
+                                             CORBA::Long studyId)
 {
   Engines::Component_var anEngine = Engines::Component::_nil();
   map<string,Engines::Component_var>::iterator itm =_listInstances_map.begin();
   while (itm != _listInstances_map.end())
+  {
+    string instance = (*itm).first;
+    SCRUTE(instance);
+    if (instance.find(registeredName) == 0)
     {
-      string instance = (*itm).first;
-      SCRUTE(instance);
-      if (instance.find(registeredName) == 0)
-        {
-          anEngine = (*itm).second;
-          if (studyId == anEngine->getStudyId())
-            {
-              return anEngine._retn();
-            }
-        }
-      itm++;
+      anEngine = (*itm).second;
+      if (studyId == anEngine->getStudyId())
+      {
+        return anEngine._retn();
+      }
     }
+    itm++;
+  }
   return anEngine._retn();  
 }
 
 //=============================================================================
+//! Find or create a new component instance
 /*! 
- *  CORBA method: find or create an instance of the component (servant),
- *  load a new component class (dynamic library) if required,
- *  ---- FOR COMPATIBILITY WITH 2.2 ---- 
- *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
- *  The servant registers itself to naming service and Registry.
- *  \param genericRegisterName  Name of the component to register
- *                              in Registry & Name Service
- *  \param componentName       Name of the constructed library of the component
- *  \return a loaded component
- */
+*  CORBA method: find or create an instance of the component (servant),
+*  load a new component class (dynamic library) if required,
+*
+*  ---- FOR COMPATIBILITY WITH 2.2 ---- 
+*
+*  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
+*
+*  The servant registers itself to naming service and Registry.
+*  \param genericRegisterName  Name of the component to register
+*                              in Registry & Name Service
+*  \param componentName       Name of the constructed library of the component
+*  \return a loaded component
+*/
 //=============================================================================
 
 Engines::Component_ptr
 Engines_Container_i::load_impl( const char* genericRegisterName,
-                                const char* componentName )
+                               const char* componentName )
 {
   string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
   Engines::Component_var iobject = Engines::Component::_nil() ;
@@ -577,13 +825,14 @@ Engines_Container_i::load_impl( const char* genericRegisterName,
     iobject = find_or_create_instance(genericRegisterName, impl_name);
   return iobject._retn();
 }
-    
+
 
 //=============================================================================
+//! Remove the component instance from container
 /*! 
- *  CORBA method: Stops the component servant, and deletes all related objects
- *  \param component_i     Component to be removed
- */
+*  CORBA method: Stops the component servant, and deletes all related objects
+*  \param component_i     Component to be removed
+*/
 //=============================================================================
 
 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
@@ -599,45 +848,47 @@ void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
 }
 
 //=============================================================================
+//! Unload component libraries from the container
 /*! 
- *  CORBA method: Discharges unused libraries from the container.
- */
+*  CORBA method: Discharges unused libraries from the container.
+*/
 //=============================================================================
 
 void Engines_Container_i::finalize_removal()
 {
   MESSAGE("finalize unload : dlclose");
   _numInstanceMutex.lock(); // lock to be alone
-                            // (see decInstanceCnt, load_component_Library)
+  // (see decInstanceCnt, load_component_Library)
   map<string, void *>::iterator ith;
   for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
+  {
+    void *handle = (*ith).second;
+    string impl_name= (*ith).first;
+    if (handle)
     {
-      void *handle = (*ith).second;
-      string impl_name= (*ith).first;
-      if (handle)
-        {
-          SCRUTE(handle);
-          SCRUTE(impl_name);
-//        dlclose(handle);                // SALOME unstable after ...
-//        _library_map.erase(impl_name);
-        }
+      SCRUTE(handle);
+      SCRUTE(impl_name);
+      //        dlclose(handle);                // SALOME unstable after ...
+      //        _library_map.erase(impl_name);
     }
+  }
   _toRemove_map.clear();
   _numInstanceMutex.unlock();
 }
 
 //=============================================================================
+//! Kill the container
 /*! 
- *  CORBA method: Kill the container process with exit(0).
- *  To remove :  never returns !
- */
+*  CORBA method: Kill the container process with exit(0).
+*  To remove :  never returns !
+*/
 //=============================================================================
 
 bool Engines_Container_i::Kill_impl()
 {
   MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
-          << _containerName.c_str() << " machineName "
-          << GetHostname().c_str());
+    << _containerName.c_str() << " machineName "
+    << Kernel_Utils::GetHostname().c_str());
   INFOS("===============================================================");
   INFOS("= REMOVE calls to Kill_impl in C++ container                  =");
   INFOS("===============================================================");
@@ -647,15 +898,16 @@ bool Engines_Container_i::Kill_impl()
 }
 
 //=============================================================================
+//! Get or create a file reference object associated to a local file (to transfer it)
 /*! 
- *  CORBA method: get or create a fileRef object associated to a local file
- *  (a file on the computer on which runs the container server), which stores
- *  a list of (machine, localFileName) corresponding to copies already done.
- 
- *  \param  origFileName absolute path for a local file to copy on other
- *          computers
- *  \return a fileRef object associated to the file.
- */
+*  CORBA method: get or create a fileRef object associated to a local file
+*  (a file on the computer on which runs the container server), which stores
+*  a list of (machine, localFileName) corresponding to copies already done.
+* 
+*  \param  origFileName absolute path for a local file to copy on other
+*          computers
+*  \return a fileRef object associated to the file.
+*/
 //=============================================================================
 
 Engines::fileRef_ptr
@@ -665,32 +917,33 @@ Engines_Container_i::createFileRef(const char* origFileName)
   Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
 
   if (origName[0] != '/')
-    {
-      INFOS("path of file to copy must be an absolute path begining with '/'");
-      return Engines::fileRef::_nil();
-    }
+  {
+    INFOS("path of file to copy must be an absolute path begining with '/'");
+    return Engines::fileRef::_nil();
+  }
 
   if (CORBA::is_nil(_fileRef_map[origName]))
-    {
-      CORBA::Object_var obj=_poa->id_to_reference(*_id);
-      Engines::Container_var pCont = Engines::Container::_narrow(obj);
-      fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
-      theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
-      _numInstanceMutex.lock() ; // lock to be alone (stl container write)
-      _fileRef_map[origName] = theFileRef;
-      _numInstanceMutex.unlock() ;
-    }
-  
+  {
+    CORBA::Object_var obj=_poa->id_to_reference(*_id);
+    Engines::Container_var pCont = Engines::Container::_narrow(obj);
+    fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
+    theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
+    _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+    _fileRef_map[origName] = theFileRef;
+    _numInstanceMutex.unlock() ;
+  }
+
   theFileRef =  Engines::fileRef::_duplicate(_fileRef_map[origName]);
   ASSERT(! CORBA::is_nil(theFileRef));
   return theFileRef._retn();
 }
 
 //=============================================================================
+//! Get a fileTransfer reference
 /*! 
- *  CORBA method:
- *  \return a reference to the fileTransfer object
- */
+*  CORBA method:
+*  \return a reference to the fileTransfer object
+*/
 //=============================================================================
 
 Engines::fileTransfer_ptr
@@ -702,141 +955,143 @@ Engines_Container_i::getFileTransfer()
 }
 
 
+//! Create a Salome file
 Engines::Salome_file_ptr 
 Engines_Container_i::createSalome_file(const char* origFileName) 
 {
   string origName(origFileName);
   if (CORBA::is_nil(_Salome_file_map[origName]))
+  {
+    Salome_file_i* aSalome_file = new Salome_file_i();
+    aSalome_file->setContainer(Engines::Container::_duplicate(this->_this()));
+    try 
     {
-      Salome_file_i* aSalome_file = new Salome_file_i();
-      aSalome_file->setContainer(Engines::Container::_duplicate(this->_this()));
-      try 
-      {
-        aSalome_file->setLocalFile(origFileName);
-        aSalome_file->recvFiles();
-      }
-      catch (const SALOME::SALOME_Exception& e)
-      {
-        return Engines::Salome_file::_nil();
-      }
-
-      Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
-      theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
-      _numInstanceMutex.lock() ; // lock to be alone (stl container write)
-      _Salome_file_map[origName] = theSalome_file;
-      _numInstanceMutex.unlock() ;
+      aSalome_file->setLocalFile(origFileName);
+      aSalome_file->recvFiles();
     }
-  
+    catch (const SALOME::SALOME_Exception& e)
+    {
+      return Engines::Salome_file::_nil();
+    }
+
+    Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
+    theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
+    _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+    _Salome_file_map[origName] = theSalome_file;
+    _numInstanceMutex.unlock() ;
+  }
+
   Engines::Salome_file_ptr theSalome_file =  
     Engines::Salome_file::_duplicate(_Salome_file_map[origName]);
   ASSERT(!CORBA::is_nil(theSalome_file));
   return theSalome_file;
 }
 //=============================================================================
+//! Finds an already existing component instance or create a new instance
 /*! 
- *  C++ method: Finds an already existing servant instance of a component, or
- *              create an instance.
- *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
- *  \param genericRegisterName    Name of the component instance to register
- *                                in Registry & Name Service,
- *                                (without _inst_n suffix, like "COMPONENT")
- *  \param componentLibraryName   like "libCOMPONENTEngine.so"
- *  \return a loaded component
- * 
- *  example with names:
- *  aGenRegisterName = COMPONENT (= first argument)
- *  impl_name = libCOMPONENTEngine.so (= second argument)
- *  _containerName = /Containers/cli76ce/FactoryServer
- *  factoryName = COMPONENTEngine_factory
- *  component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
- *
- *  instanceName = COMPONENT_inst_1
- *  component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
- */
+*  C++ method: Finds an already existing servant instance of a component, or
+*              create an instance.
+*  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
+*  \param genericRegisterName    Name of the component instance to register
+*                                in Registry & Name Service,
+*                                (without _inst_n suffix, like "COMPONENT")
+*  \param componentLibraryName   like "libCOMPONENTEngine.so"
+*  \return a loaded component
+* 
+*  example with names:
+*    - aGenRegisterName = COMPONENT (= first argument)
+*    - impl_name = libCOMPONENTEngine.so (= second argument)
+*    - _containerName = /Containers/cli76ce/FactoryServer
+*    - factoryName = COMPONENTEngine_factory
+*    - component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
+*    - instanceName = COMPONENT_inst_1
+*    - component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
+*/
 //=============================================================================
 
 Engines::Component_ptr
-Engines_Container_i::find_or_create_instance(string genericRegisterName,
-                                             string componentLibraryName)
+Engines_Container_i::find_or_create_instance(std::string genericRegisterName,
+                                             std::string componentLibraryName)
 {
   string aGenRegisterName = genericRegisterName;
   string impl_name = componentLibraryName;
   if (_library_map.count(impl_name) == 0) 
-    {
-      INFOS("shared library " << impl_name <<" must be loaded before creating instance");
-      return Engines::Component::_nil() ;
-    }
+  {
+    INFOS("shared library " << impl_name <<" must be loaded before creating instance");
+    return Engines::Component::_nil() ;
+  }
   else
-    {
-      // --- find a registered instance in naming service, or create
+  {
+    // --- find a registered instance in naming service, or create
 
-      void* handle = _library_map[impl_name];
-      string component_registerBase =
-        _containerName + "/" + aGenRegisterName;
-      Engines::Component_var iobject = Engines::Component::_nil() ;
-      try
+    void* handle = _library_map[impl_name];
+    string component_registerBase =
+      _containerName + "/" + aGenRegisterName;
+    Engines::Component_var iobject = Engines::Component::_nil() ;
+    try
+    {
+      CORBA::Object_var obj =
+        _NS->ResolveFirst( component_registerBase.c_str());
+      if ( CORBA::is_nil( obj ) )
+      {
+        iobject = createInstance(genericRegisterName,
+          handle,
+          0); // force multiStudy instance here !
+      }
+      else
+      { 
+        iobject = Engines::Component::_narrow( obj ) ;
+        Engines_Component_i *servant =
+          dynamic_cast<Engines_Component_i*>
+          (_poa->reference_to_servant(iobject));
+        ASSERT(servant)
+          int studyId = servant->getStudyId();
+        ASSERT (studyId >= 0);
+        if (studyId == 0) // multiStudy instance, OK
         {
-          CORBA::Object_var obj =
-            _NS->ResolveFirst( component_registerBase.c_str());
-          if ( CORBA::is_nil( obj ) )
-            {
-              iobject = createInstance(genericRegisterName,
-                                       handle,
-                                       0); // force multiStudy instance here !
-            }
-          else
-            { 
-              iobject = Engines::Component::_narrow( obj ) ;
-              Engines_Component_i *servant =
-                dynamic_cast<Engines_Component_i*>
-                (_poa->reference_to_servant(iobject));
-              ASSERT(servant)
-              int studyId = servant->getStudyId();
-              ASSERT (studyId >= 0);
-              if (studyId == 0) // multiStudy instance, OK
-                {
-                  // No ReBind !
-                  MESSAGE(component_registerBase.c_str()<<" already bound");
-                }
-              else // monoStudy instance: NOK
-                {
-                  iobject = Engines::Component::_nil();
-                  INFOS("load_impl & find_component_instance methods "
-                        << "NOT SUITABLE for mono study components");
-                }
-            }
+          // No ReBind !
+          MESSAGE(component_registerBase.c_str()<<" already bound");
         }
-      catch (...)
+        else // monoStudy instance: NOK
         {
-          INFOS( "Container_i::load_impl catched" ) ;
+          iobject = Engines::Component::_nil();
+          INFOS("load_impl & find_component_instance methods "
+            << "NOT SUITABLE for mono study components");
         }
-      return iobject._retn();
+      }
     }
+    catch (...)
+    {
+      INFOS( "Container_i::load_impl catched" ) ;
+    }
+    return iobject._retn();
+  }
 }
 
 //=============================================================================
+//! Create a new component instance 
 /*! 
- *  C++ method: create a servant instance of a component.
- *  \param genericRegisterName    Name of the component instance to register
- *                                in Registry & Name Service,
- *                                (without _inst_n suffix, like "COMPONENT")
- *  \param handle                 loaded library handle
- *  \param studyId                0 for multiStudy instance, 
- *                                study Id (>0) otherwise
- *  \return a loaded component
- 
- *  example with names:
- *  aGenRegisterName = COMPONENT (= first argument)
- *  _containerName = /Containers/cli76ce/FactoryServer
- *  factoryName = COMPONENTEngine_factory
- *  component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
- *  instanceName = COMPONENT_inst_1
- *  component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
- */
+*  C++ method: create a servant instance of a component.
+*  \param genericRegisterName    Name of the component instance to register
+*                                in Registry & Name Service,
+*                                (without _inst_n suffix, like "COMPONENT")
+*  \param handle                 loaded library handle
+*  \param studyId                0 for multiStudy instance, 
+*                                study Id (>0) otherwise
+*  \return a loaded component
+* 
+*  example with names:
+*    - aGenRegisterName = COMPONENT (= first argument)
+*    - _containerName = /Containers/cli76ce/FactoryServer
+*    - factoryName = COMPONENTEngine_factory
+*    - component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
+*    - instanceName = COMPONENT_inst_1
+*    - component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
+*/
 //=============================================================================
 
 Engines::Component_ptr
-Engines_Container_i::createInstance(string genericRegisterName,
+Engines_Container_i::createInstance(std::string genericRegisterName,
                                     void *handle,
                                     int studyId)
 {
@@ -848,12 +1103,12 @@ Engines_Container_i::createInstance(string genericRegisterName,
 
   typedef  PortableServer::ObjectId * (*FACTORY_FUNCTION)
     (CORBA::ORB_ptr,
-     PortableServer::POA_ptr, 
-     PortableServer::ObjectId *, 
-     const char *, 
-     const char *) ;
+    PortableServer::POA_ptr, 
+    PortableServer::ObjectId *, 
+    const char *, 
+    const char *) ;
 
-#ifndef WNT
+#ifndef WIN32
   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)dlsym( handle, factory_name.c_str() );
 #else
   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)GetProcAddress( (HINSTANCE)handle, factory_name.c_str() );
@@ -861,11 +1116,11 @@ Engines_Container_i::createInstance(string genericRegisterName,
 
   if ( !Component_factory )
   {
-      INFOS( "Can't resolve symbol: " + factory_name );
-#ifndef WNT
-      SCRUTE( dlerror() );
+    INFOS( "Can't resolve symbol: " + factory_name );
+#ifndef WIN32
+    SCRUTE( dlerror() );
 #endif
-      return Engines::Component::_nil() ;
+    return Engines::Component::_nil() ;
   }
 
   // --- create instance
@@ -873,67 +1128,66 @@ Engines_Container_i::createInstance(string genericRegisterName,
   Engines::Component_var iobject = Engines::Component::_nil() ;
 
   try
-    {
-      _numInstanceMutex.lock() ; // lock on the instance number
-      _numInstance++ ;
-      int numInstance = _numInstance ;
-      _numInstanceMutex.unlock() ;
-
-      char aNumI[12];
-      sprintf( aNumI , "%d" , numInstance ) ;
-      string instanceName = aGenRegisterName + "_inst_" + aNumI ;
-      string component_registerName =
-        _containerName + "/" + instanceName;
-
-      // --- Instanciate required CORBA object
-
-      PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
-      id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
-                                 aGenRegisterName.c_str() ) ;
-      if (id == NULL)
-        return iobject._retn();
-      
-      // --- get reference & servant from id
-
-      CORBA::Object_var obj = _poa->id_to_reference(*id);
-      iobject = Engines::Component::_narrow( obj ) ;
-
-      Engines_Component_i *servant =
-        dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
-      ASSERT(servant);
-      //SCRUTE(servant->pd_refCount);
-      servant->_remove_ref(); // compensate previous id_to_reference 
-      //SCRUTE(servant->pd_refCount);
-      _numInstanceMutex.lock() ; // lock to be alone (stl container write)
-      _listInstances_map[instanceName] = iobject;
-      _cntInstances_map[aGenRegisterName] += 1;
-      _numInstanceMutex.unlock() ;
-      SCRUTE(aGenRegisterName);
-      SCRUTE(_cntInstances_map[aGenRegisterName]);
-      //SCRUTE(servant->pd_refCount);
-      bool ret_studyId = servant->setStudyId(studyId);
-      ASSERT(ret_studyId);
-
-      // --- register the engine under the name
-      //     containerName(.dir)/instanceName(.object)
+  {
+    _numInstanceMutex.lock() ; // lock on the instance number
+    _numInstance++ ;
+    int numInstance = _numInstance ;
+    _numInstanceMutex.unlock() ;
+
+    char aNumI[12];
+    sprintf( aNumI , "%d" , numInstance ) ;
+    string instanceName = aGenRegisterName + "_inst_" + aNumI ;
+    string component_registerName =
+      _containerName + "/" + instanceName;
+
+    // --- Instanciate required CORBA object
+
+    PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
+    id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
+      aGenRegisterName.c_str() ) ;
+    if (id == NULL)
+      return iobject._retn();
 
-      _NS->Register( iobject , component_registerName.c_str() ) ;
-      MESSAGE( component_registerName.c_str() << " bound" ) ;
-    }
+    // --- get reference & servant from id
+
+    CORBA::Object_var obj = _poa->id_to_reference(*id);
+    iobject = Engines::Component::_narrow( obj ) ;
+
+    Engines_Component_i *servant =
+      dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
+    ASSERT(servant);
+    //SCRUTE(servant->_refcount_value());
+    _numInstanceMutex.lock() ; // lock to be alone (stl container write)
+    _listInstances_map[instanceName] = iobject;
+    _cntInstances_map[aGenRegisterName] += 1;
+    _numInstanceMutex.unlock() ;
+    SCRUTE(aGenRegisterName);
+    SCRUTE(_cntInstances_map[aGenRegisterName]);
+    servant->setStudyId(studyId);
+    servant->_remove_ref(); // do not need servant any more (remove ref from reference_to_servant)
+    //SCRUTE(servant->_refcount_value());
+
+    // --- register the engine under the name
+    //     containerName(.dir)/instanceName(.object)
+
+    _NS->Register( iobject , component_registerName.c_str() ) ;
+    MESSAGE( component_registerName.c_str() << " bound" ) ;
+  }
   catch (...)
-    {
-      INFOS( "Container_i::createInstance exception catched" ) ;
-    }
+  {
+    INFOS( "Container_i::createInstance exception catched" ) ;
+  }
   return iobject._retn();
 }
 
 //=============================================================================
+//! Decrement component instance reference count
 /*! 
- *
- */
+*
+*/
 //=============================================================================
 
-void Engines_Container_i::decInstanceCnt(string genericRegisterName)
+void Engines_Container_i::decInstanceCnt(std::string genericRegisterName)
 {
   if(_cntInstances_map.count(genericRegisterName)==0)
     return;
@@ -941,25 +1195,26 @@ void Engines_Container_i::decInstanceCnt(string genericRegisterName)
   MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName);
   ASSERT(_cntInstances_map[aGenRegisterName] > 0); 
   _numInstanceMutex.lock(); // lock to be alone
-                            // (see finalize_removal, load_component_Library)
+  // (see finalize_removal, load_component_Library)
   _cntInstances_map[aGenRegisterName] -= 1;
   SCRUTE(_cntInstances_map[aGenRegisterName]);
   if (_cntInstances_map[aGenRegisterName] == 0)
-    {
-      string impl_name =
-        Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
-      SCRUTE(impl_name);
-      void* handle = _library_map[impl_name];
-      ASSERT(handle);
-      _toRemove_map[impl_name] = handle;
-    }
+  {
+    string impl_name =
+      Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
+    SCRUTE(impl_name);
+    void* handle = _library_map[impl_name];
+    ASSERT(handle);
+    _toRemove_map[impl_name] = handle;
+  }
   _numInstanceMutex.unlock();
 }
 
 //=============================================================================
+//! Indicate if container is a python one
 /*! 
- *  Retrieves only with container naming convention if it is a python container
- */
+*  Retrieves only with container naming convention if it is a python container
+*/
 //=============================================================================
 
 bool Engines_Container_i::isPythonContainer(const char* ContainerName)
@@ -974,39 +1229,40 @@ bool Engines_Container_i::isPythonContainer(const char* ContainerName)
 
 //=============================================================================
 /*! 
- *  
- */
+*  
+*/
 //=============================================================================
 
 void ActSigIntHandler()
 {
-#ifndef WNT
+#ifndef WIN32
   struct sigaction SigIntAct ;
   SigIntAct.sa_sigaction = &SigIntHandler ;
+  sigemptyset(&SigIntAct.sa_mask);
   SigIntAct.sa_flags = SA_SIGINFO ;
 #endif
 
-// DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
-// (SIGINT | SIGUSR1) :
-// it must be only one signal ===> one call for SIGINT 
-// and an other one for SIGUSR1
+  // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
+  // (SIGINT | SIGUSR1) :
+  // it must be only one signal ===> one call for SIGINT 
+  // and an other one for SIGUSR1
 
-#ifndef WNT
+#ifndef WIN32
   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) 
-    {
-      perror("SALOME_Container main ") ;
-      exit(0) ;
-    }
+  {
+    perror("SALOME_Container main ") ;
+    exit(0) ;
+  }
   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) )
-    {
-      perror("SALOME_Container main ") ;
-      exit(0) ;
-    }
+  {
+    perror("SALOME_Container main ") ;
+    exit(0) ;
+  }
   if ( sigaction( SIGUSR2 , &SigIntAct, NULL ) )
-    {
-      perror("SALOME_Container main ") ;
-      exit(0) ;
-    }
+  {
+    perror("SALOME_Container main ") ;
+    exit(0) ;
+  }
 
   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
   //             use of streams (and so on) should never be used because :
@@ -1026,7 +1282,7 @@ void ActSigIntHandler()
 void SetCpuUsed() ;
 void CallCancelThread() ;
 
-#ifndef WNT
+#ifndef WIN32
 void SigIntHandler(int what ,
                    siginfo_t * siginfo ,
                    void * toto ) 
@@ -1043,71 +1299,161 @@ void SigIntHandler(int what ,
   //          << "              si_pid   " << siginfo->si_pid) ;
 
   if ( _Sleeping )
+  {
+    _Sleeping = false ;
+    //     MESSAGE("SigIntHandler END sleeping.") ;
+    return ;
+  }
+  else
+  {
+    ActSigIntHandler() ;
+    if ( siginfo->si_signo == SIGUSR1 )
     {
-      _Sleeping = false ;
-      //     MESSAGE("SigIntHandler END sleeping.") ;
-      return ;
+      SetCpuUsed() ;
     }
-  else
+    else if ( siginfo->si_signo == SIGUSR2 )
     {
-      ActSigIntHandler() ;
-      if ( siginfo->si_signo == SIGUSR1 )
-        {
-          SetCpuUsed() ;
-        }
-      else if ( siginfo->si_signo == SIGUSR2 )
-        {
-          CallCancelThread() ;
-        }
-      else 
-        {
-          _Sleeping = true ;
-          //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
-          int count = 0 ;
-          while( _Sleeping )
-            {
-              sleep( 1 ) ;
-              count += 1 ;
-            }
-          //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
-        }
-      return ;
+      CallCancelThread() ;
     }
+    else 
+    {
+      _Sleeping = true ;
+      //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
+      int count = 0 ;
+      while( _Sleeping )
+      {
+        sleep( 1 ) ;
+        count += 1 ;
+      }
+      //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
+    }
+    return ;
+  }
 }
-#else // Case WNT
+#else // Case WIN32
 void SigIntHandler( int what )
 {
-#ifndef WNT
+#ifndef WIN32
   MESSAGE( pthread_self() << "SigIntHandler what     " << what << endl );
 #else
   MESSAGE( "SigIntHandler what     " << what << endl );
 #endif
   if ( _Sleeping )
+  {
+    _Sleeping = false ;
+    MESSAGE("SigIntHandler END sleeping.") ;
+    return ;
+  }
+  else
+  {
+    ActSigIntHandler() ;
+    if ( what == SIGUSR1 )
     {
-      _Sleeping = false ;
-      MESSAGE("SigIntHandler END sleeping.") ;
-      return ;
+      SetCpuUsed() ;
     }
-  else
+    else
     {
-      ActSigIntHandler() ;
-      if ( what == SIGUSR1 )
-        {
-          SetCpuUsed() ;
-        }
-      else
+      _Sleeping = true ;
+      MESSAGE("SigIntHandler BEGIN sleeping.") ;
+      int count = 0 ;
+      while( _Sleeping ) 
+      {
+        Sleep( 1000 ) ;
+        count += 1 ;
+      }
+      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
+    }
+    return ;
+  }
+}
+#endif
+
+/*! \brief copy a file from a remote host (container) to the local host
+ * \param container the remote container
+ * \param remoteFile the file to copy locally from the remote host into localFile
+ * \param localFile the local file
+ */
+void Engines_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
+{
+  Engines::fileTransfer_var fileTransfer = container->getFileTransfer();
+
+  FILE* fp;
+  if ((fp = fopen(localFile,"wb")) == NULL)
+    {
+      INFOS("file " << localFile << " cannot be open for writing");
+      return;
+    }
+
+  CORBA::Long fileId = fileTransfer->open(remoteFile);
+  if (fileId > 0)
+    {
+      Engines::fileBlock* aBlock;
+      int toFollow = 1;
+      int ctr=0;
+      while (toFollow)
         {
-          _Sleeping = true ;
-          MESSAGE("SigIntHandler BEGIN sleeping.") ;
-          int count = 0 ;
-          while( _Sleeping ) 
-            {
-              Sleep( 1000 ) ;
-              count += 1 ;
-            }
-          MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
+          ctr++;
+          SCRUTE(ctr);
+          aBlock = fileTransfer->getBlock(fileId);
+          toFollow = aBlock->length();
+          SCRUTE(toFollow);
+          CORBA::Octet *buf = aBlock->get_buffer();
+          fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
+          delete aBlock;
         }
-      return ;
+      fclose(fp);
+      MESSAGE("end of transfer");
+      fileTransfer->close(fileId);
+    }
+  else
+    {
+      INFOS("open reference file for copy impossible");
     }
 }
-#endif
+
+/*! \brief create a PyNode object to execute remote python code
+ * \param nodeName the name of the node
+ * \param code the python code to load
+ * \return the PyNode
+ */
+Engines::PyNode_ptr Engines_Container_i::createPyNode(const char* nodeName, const char* code)
+{
+    Engines::PyNode_var node= Engines::PyNode::_nil();
+
+    PyGILState_STATE gstate = PyGILState_Ensure();
+    PyObject *res = PyObject_CallMethod(_pyCont,
+      (char*)"create_pynode",
+      (char*)"ss",
+      nodeName,
+      code);
+    if(res==NULL)
+      {
+        //internal error
+        PyErr_Print();
+        PyGILState_Release(gstate);
+        SALOME::ExceptionStruct es;
+        es.type = SALOME::INTERNAL_ERROR;
+        es.text = "can not create a python node";
+        throw SALOME::SALOME_Exception(es);
+      }
+    long ierr=PyInt_AsLong(PyTuple_GetItem(res,0));
+    PyObject* result=PyTuple_GetItem(res,1);
+    std::string astr=PyString_AsString(result);
+    Py_DECREF(res);
+    PyGILState_Release(gstate);
+
+    if(ierr==0)
+      {
+        CORBA::Object_var obj = _orb->string_to_object(astr.c_str());
+        node = Engines::PyNode::_narrow(obj);
+        return node._retn();
+      }
+    else
+      {
+        SALOME::ExceptionStruct es;
+        es.type = SALOME::INTERNAL_ERROR;
+        es.text = astr.c_str();
+        throw SALOME::SALOME_Exception(es);
+      }
+
+}