Salome HOME
CCAR: add the PyNode object that can be created in a container
[modules/kernel.git] / src / Container / Container_i.cxx
index 7c30632954304c5e924871793d4b1445f8e7319f..f7124ac82ba1074dd5e62579b0db86329bf985ff 100644 (file)
@@ -1,60 +1,57 @@
-//  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
 //
-//  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//  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
+//
+//  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 WIN32
 #include <sys/time.h>
-#ifndef WNT
 #include <dlfcn.h>
 #include <unistd.h>
 #else
-#include "../../adm/win32/SALOME_WNT.hxx"
 #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)
-#else
-#include <SALOME_Component.hh>
-#endif
+#include CORBA_SERVER_HEADER(SALOME_Exception)
 #include <pthread.h>  // must be before Python.h !
 #include "SALOME_Container_i.hxx"
 #include "SALOME_Component_i.hxx"
 #include "SALOME_FileRef_i.hxx"
 #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"
@@ -67,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
+#ifndef WIN32
 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
 #else
-  extern "C" {void SigIntHandler( int ) ; }
+extern "C" {void SigIntHandler( int ) ; }
+#endif
+
+#ifdef WIN32
+# define separator '\\'
+#else
+# define separator '/'
 #endif
 
 
@@ -84,31 +83,42 @@ 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, 
-                                         PortableServer::POA_var poa,
-                                         char *containerName ,
+                                          PortableServer::POA_ptr poa,
+                                          char *containerName ,
                                           int argc , char* argv[],
-                                         bool activAndRegist,
-                                         bool isServantAloneInProcess
-                                         ) :
-  _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
+                                          bool activAndRegist,
+                                          bool isServantAloneInProcess
+                                          ) :
+  _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess),_id(0),_NS(0)
 {
   _pid = (long)getpid();
 
@@ -118,125 +128,178 @@ Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
   _argc = argc ;
   _argv = argv ;
 
-  string hostname = GetHostname();
-  MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
-         << _argc << " Thread " << pthread_self() ) ;
+  string hostname = Kernel_Utils::GetHostname();
+#ifndef WIN32
+  MESSAGE(hostname << " " << getpid() << 
+    " Engines_Container_i starting argc " <<
+    _argc << " Thread " << pthread_self() ) ;
+#else
+  MESSAGE(hostname << " " << _getpid() << 
+    " 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( CORBA::ORB::_duplicate(_orb) ) ;
-      CORBA::Object_var obj=_poa->id_to_reference(*_id);
-      Engines::Container_var pCont 
-       = Engines::Container::_narrow(obj);
-
-      _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)
-       {
-         Py_ACQUIRE_NEW_THREAD;
-#ifdef WNT
-         // mpv: this is temporary solution: there is a unregular crash if not
-         Sleep(2000);
-         PyRun_SimpleString("import sys\n");
-         // first element is the path to Registry.dll, but it's wrong
-         PyRun_SimpleString("sys.path = sys.path[1:]\n");
+      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());
-         Py_RELEASE_NEW_THREAD;
-       }
+      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");
 
-      fileTransfer_i* aFileTransfer = new fileTransfer_i();
-      _fileTransfer = Engines::fileTransfer::_narrow(aFileTransfer->_this());
+      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 method: Get the hostName of the Container (without domain extensions)
- */
+*  CORBA attribute: Container working directory 
+*/
+//=============================================================================
+
+char* Engines_Container_i::workingdir()
+{
+  char wd[256];
+  getcwd (wd,256);
+  return CORBA::string_dup(wd) ;
+}
+
+//=============================================================================
+//! Get container log file name
+/*! 
+*  CORBA attribute: Container log file name
+*/
+//=============================================================================
+
+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)
+*/
 //=============================================================================
 
 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()
@@ -245,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()
@@ -256,38 +320,179 @@ 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()
 {
   MESSAGE("Engines_Container_i::Shutdown()");
+
+  /* For each component contained in this container
+  * tell it to self-destroy
+  */
+  std::map<std::string, Engines::Component_var>::iterator itm;
+  for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
+    {
+      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());
-  //_remove_ref();
-  //_poa->deactivate_object(*_id);
+  _NS->Destroy_Name(_containerName.c_str());
   if(_isServantAloneInProcess)
-    {
-      MESSAGE("Effective Shutdown of container Begins...");
-      LocalTraceBufferPool* bp1 = LocalTraceBufferPool::instance();
-      bp1->deleteInstance(bp1);
+  {
+    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 )
+    {
+      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
@@ -298,217 +503,321 @@ 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[impl_name]) _toRemove_map.erase(impl_name);
-  if (_library_map[impl_name])
-    {
-      MESSAGE("Library " << impl_name << " already loaded");
-      _numInstanceMutex.unlock();
-      return true;
-    }
-  
+  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;
+  }
+
+  std::string retso="";
+#ifndef WIN32
   void* handle;
-#if defined( WNT )
-  handle = dlopen( impl_name.c_str() , 0 ) ;
-//#elif defined( __osf1__ )
-//  handle = dlopen( impl_name.c_str() , RTLD_NOW ) ;
-#else
   handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
+  if ( !handle )retso=dlerror();
+#else
+  HINSTANCE handle;
+  handle = LoadLibrary( impl_name.c_str() );
 #endif
+
   if ( handle )
-    {
-      _library_map[impl_name] = handle;
-      _numInstanceMutex.unlock();
-      return true;
-    }
-  else
-    {
-      INFOS("Can't load shared library : " << impl_name);
-      INFOS("error dlopen: " << dlerror());
-    }
+  {
+    _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;
-    }
-  if (_library_map[aCompName])
-    {
-      return true; // Python Component, already imported
-    }
+  {
+    INFOS("Supervision Container does not support Python Component Engines");
+    return false;
+  }
+  if (_library_map.count(aCompName) != 0)
+  {
+    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);
-      SCRUTE(ret);
-      Py_RELEASE_NEW_THREAD;
-  
-      if (ret) // import possible: Python component
-       {
-         _library_map[aCompName] = (void *)pyCont; // any non O value OK
-         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
 Engines_Container_i::create_component_instance(const char*genericRegisterName,
-                                              CORBA::Long studyId)
+                                               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[aCompName]) // Python component
+  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);
-      SCRUTE(iors);
-      Py_RELEASE_NEW_THREAD;
-  
-      if( iors!="" )
-      {
-       CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
-       iobject = Engines::Component::_narrow( obj ) ;
-      }
-      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
-  void* handle = _library_map[impl_name];
-  if ( !handle )
+  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 )
     {
-      INFOS("shared library " << impl_name <<"must be loaded before instance");
-      return Engines::Component::_nil() ;
+#ifndef WIN32
+      sleep( 1 ) ;
+#else
+      Sleep(1000);
+#endif
+      count-- ;
+      MESSAGE( count << ". Waiting for component " << genericRegisterName);
+      obj = _NS->Resolve(component_registerName.c_str());
     }
-  else
+
+    if(CORBA::is_nil(obj))
+    {
+      MESSAGE("SALOME_Container::create_component_instance failed");
+      return Engines::Component::_nil();
+    }
+    else
     {
-      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() ;
@@ -516,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)
@@ -530,51 +840,55 @@ void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
   ASSERT(! CORBA::is_nil(component_i));
   string instanceName = component_i->instanceName() ;
   MESSAGE("unload component " << instanceName);
+  _numInstanceMutex.lock() ; // lock to be alone (stl container write)
   _listInstances_map.erase(instanceName);
+  _numInstanceMutex.unlock() ;
   component_i->destroy() ;
   _NS->Destroy_Name(instanceName.c_str());
 }
 
 //=============================================================================
+//! 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("===============================================================");
@@ -584,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
@@ -602,30 +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());
-      _fileRef_map[origName] = theFileRef;
-    }
-  
+  {
+    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
@@ -637,113 +955,145 @@ 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 
+    {
+      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;
-  void* handle = _library_map[impl_name];
-  if ( !handle )
+  if (_library_map.count(impl_name) == 0) 
+  {
+    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
+
+    void* handle = _library_map[impl_name];
+    string component_registerBase =
+      _containerName + "/" + aGenRegisterName;
+    Engines::Component_var iobject = Engines::Component::_nil() ;
+    try
     {
-      INFOS("shared library " << impl_name <<"must be loaded before instance");
-      return Engines::Component::_nil() ;
+      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");
+        }
+      }
     }
-  else
+    catch (...)
     {
-      // --- find a registered instance in naming service, or create
-
-      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
-               {
-                 // 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");
-               }
-           }
-       }
-      catch (...)
-       {
-         INFOS( "Container_i::load_impl catched" ) ;
-       }
-      return iobject._retn();
+      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,
-                                   void *handle,
-                                   int studyId)
+Engines_Container_i::createInstance(std::string genericRegisterName,
+                                    void *handle,
+                                    int studyId)
 {
   // --- find the factory
 
@@ -753,108 +1103,118 @@ 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 *) ;
 
-  FACTORY_FUNCTION Component_factory
-    = (FACTORY_FUNCTION) dlsym(handle, factory_name.c_str());
+#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() );
+#endif
 
-  char *error ;
-  if ( (error = dlerror() ) != NULL)
-    {
-      INFOS("Can't resolve symbol: " + factory_name);
-      SCRUTE(error);
-      return Engines::Component::_nil() ;
-    }
+  if ( !Component_factory )
+  {
+    INFOS( "Can't resolve symbol: " + factory_name );
+#ifndef WIN32
+    SCRUTE( dlerror() );
+#endif
+    return Engines::Component::_nil() ;
+  }
 
   // --- create instance
 
   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() ) ;
-
-      // --- get reference & servant from id
-
-      CORBA::Object_var obj = _poa->id_to_reference(*id);
-      iobject = Engines::Component::_narrow( obj ) ;
+  {
+    _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();
 
-      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);
-      _listInstances_map[instanceName] = iobject;
-      _cntInstances_map[aGenRegisterName] += 1;
-      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)
-
-      _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;
   string aGenRegisterName =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)
@@ -869,34 +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) ;
+  }
 
   //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 :
@@ -914,11 +1280,12 @@ void ActSigIntHandler()
 }
 
 void SetCpuUsed() ;
+void CallCancelThread() ;
 
-#ifndef WNT
+#ifndef WIN32
 void SigIntHandler(int what ,
-                  siginfo_t * siginfo ,
-                  void * toto ) 
+                   siginfo_t * siginfo ,
+                   void * toto ) 
 {
   //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 :
@@ -932,64 +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 
-       {
-         _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 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 ;
+      _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)
+        {
+          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;
+        }
+      fclose(fp);
+      MESSAGE("end of transfer");
+      fileTransfer->close(fileId);
+    }
+  else
+    {
+      INFOS("open reference file for copy impossible");
+    }
+}
+
+/*! \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);
+      }
+
+}