]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
[CEA 506] Connect light SALOME modules to "Dump Study" operation
authorsan <san@opencascade.com>
Wed, 9 Nov 2011 16:27:58 +0000 (16:27 +0000)
committersan <san@opencascade.com>
Wed, 9 Nov 2011 16:27:58 +0000 (16:27 +0000)
Issue #21377 (http://salome.mantis.opencascade.com/view.php?id=21377)

14 files changed:
src/LightApp/LightApp_DataModel.cxx
src/LightApp/LightApp_DataModel.h
src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.cxx
src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.h
src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx
src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h
src/SalomeApp/SalomeApp_Application.cxx
src/SalomeApp/SalomeApp_Application.h
src/SalomeApp/SalomeApp_Study.cxx
src/SalomeApp/SalomeApp_Study.h
src/Session/SalomeApp_Engine_i.cxx
src/Session/SalomeApp_Engine_i.hxx
src/Session/Session_ServerLauncher.cxx
src/Session/Session_ServerThread.cxx

index 0c8c40888a77a0f02dacb05644dbcdb389d4898a..8c967590567c8dfa10bfc31e43734416595f55d9 100644 (file)
@@ -79,6 +79,15 @@ bool LightApp_DataModel::saveAs( const QString&, CAM_Study*, QStringList& )
   return true;
 }
 
+/*!
+  Does nothing by default. Should be redefined in light modules
+  that want to participate in "Dump study" operation.
+*/
+bool LightApp_DataModel::dumpPython( const QString&, CAM_Study*, bool, QStringList& )
+{
+  return true;
+}
+
 /*!
   Emit closed()
 */
index 994cbecaaf414b4d17cde861ca99585c9644e7f5..4da6d3675f72f42ca8c9fcbef3f3de9baba28f05 100644 (file)
@@ -55,6 +55,10 @@ public:
   virtual bool                        save( QStringList& );
   virtual bool                        saveAs( const QString&, CAM_Study*, QStringList& );
   virtual bool                        close();
+  virtual bool                        dumpPython( const QString&,
+                                                 CAM_Study*,
+                                                 bool,
+                                                 QStringList& );
 
   virtual void                        update( LightApp_DataObject* = 0, LightApp_Study* = 0 );
 
index 17c8f531b355012e2331b34dbea59a35cc99e493..2fc1d07c56da23e5f1d342c23783a6eb39b0e53f 100644 (file)
@@ -115,6 +115,37 @@ bool SALOME_PYQT_DataModelLight::create( CAM_Study* study )
   return true;
 }
 
+//=================================================================================
+// function : dumpPython()
+// purpose  : Re-defined from LigthApp_DataModel in order to participate 
+//            in dump study process
+//=================================================================================
+bool SALOME_PYQT_DataModelLight::dumpPython( const QString& theURL, 
+                                            CAM_Study* theStudy,
+                                            bool isMultiFile,
+                                            QStringList& theListOfFiles )
+{
+  MESSAGE("SALOME_PYQT_DataModelLight::dumpPython()");
+  
+  LightApp_DataModel::dumpPython( theURL, theStudy, isMultiFile, theListOfFiles );
+
+  LightApp_Study* study = dynamic_cast<LightApp_Study*>( theStudy );
+  SALOME_PYQT_ModuleLight* aModule = dynamic_cast<SALOME_PYQT_ModuleLight*>(module());
+
+  if(!aModule || !study)
+    return false;
+  
+  std::string aTmpDir = study->GetTmpDir( theURL.toLatin1().constData(), isMultiFile );
+
+  theListOfFiles.append( QString( aTmpDir.c_str() ) );
+  int oldSize = theListOfFiles.size();
+
+  aModule->dumpPython( theListOfFiles );
+
+  //Return true if some items have been added, else return false 
+  return theListOfFiles.size() > oldSize;
+}
+
 //=================================================================================
 // function : isModified()
 // purpose  : default implementation, always returns false so as not to mask study's isModified()
index 2a6c2f21d37138f6c3550d39419d2dc89e71169f..6f604cdc3f2c6cf08d9e01c49730183289923ca7 100644 (file)
@@ -46,6 +46,10 @@ public:
   virtual bool         saveAs ( const QString&, CAM_Study*, QStringList& );
   virtual bool         close  ();
   virtual bool         create ( CAM_Study* );
+  virtual bool         dumpPython( const QString&,
+                                  CAM_Study*,
+                                  bool,
+                                  QStringList& );
   
   virtual bool         isModified () const;
   virtual bool         isSaved    () const;
index a28601bafd959d2a1a6c57de1683e3b866cde697..825034ad7ba60e12bc3fe6e0bda80873f05be183 100644 (file)
@@ -2481,6 +2481,76 @@ void SALOME_PYQT_ModuleLight::saveEvent(QStringList& theListOfFiles)
   }
 }
 
+/*
+ * Python dump request.
+ * Called when user activates dump study operation.
+ */
+void SALOME_PYQT_ModuleLight::dumpPython(QStringList& theListOfFiles)
+{
+  MESSAGE("SALOME_PYQT_ModuleLight::dumpPython()")
+  // perform synchronous request to Python event dispatcher
+  class DumpEvent: public PyInterp_LockRequest
+  {
+  public:     
+    DumpEvent(PyInterp_Interp*          _py_interp,
+              SALOME_PYQT_ModuleLight*  _obj,
+              QStringList&              _files_list)
+      : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true)
+        myObj( _obj ) ,
+        myFilesList(_files_list) {}
+  protected:
+    virtual void execute()
+    {
+      myObj->dumpEvent(myFilesList);
+    }
+  private:
+    SALOME_PYQT_ModuleLight* myObj;
+    QStringList&             myFilesList;
+  };
+  
+  // Posting the request only if dispatcher is not busy!
+  // Executing the request synchronously
+  if ( !PyInterp_Dispatcher::Get()->IsBusy() )
+    PyInterp_Dispatcher::Get()->Exec( new DumpEvent( myInterp, this, theListOfFiles ) );
+}
+
+void SALOME_PYQT_ModuleLight::dumpEvent(QStringList& theListOfFiles)
+{
+  MESSAGE("SALOME_PYQT_ModuleLight::dumpEvent()");
+  QStringList::Iterator it = theListOfFiles.begin();
+  // Python interpreter should be initialized and Python module should be
+  // import first
+  if ( !myInterp || !myModule || (it == theListOfFiles.end()))
+    return;
+
+  if ( PyObject_HasAttrString(myModule, (char*)"dumpStudy") ) {
+    PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"dumpStudy",
+                                           (char*)"s", (*it).toLatin1().constData()));
+    if( !res ) {
+      PyErr_Print();
+    }
+    else{
+      // parse the return value
+      // result can be one string...
+      if ( PyString_Check( res ) ) {
+        QString astr = PyString_AsString( res );
+        //SCRUTE(astr);
+        theListOfFiles.append(astr);
+      }
+      //also result can be a list...
+      else if ( PyList_Check( res ) ) {
+        int size = PyList_Size( res );
+        for ( int i = 0; i < size; i++ ) {
+          PyObject* value = PyList_GetItem( res, i );
+          if( value && PyString_Check( value ) ) {
+            theListOfFiles.append( PyString_AsString( value ) );
+          }
+        }
+      }
+    }
+  }
+}
+
 /*
  * Open study request.
  * Called when user open study.
index 6917f3a1df26dd4cc1eb7721654aab64cdb0d54b..dbc6d21e8d7a8bf6c55efca393da21642bc4a072 100644 (file)
@@ -123,9 +123,9 @@ public:
   void                       setPreferenceProperty( const int, const QString&, 
                                                     const QVariant& );
 
-  void                   save(QStringList& theListOfFiles);
-
-  bool                   open(QStringList theListOfFiles);
+  void                       save(QStringList& theListOfFiles);
+  bool                       open(QStringList theListOfFiles);
+  void                       dumpPython(QStringList& theListOfFiles);
 
   /*create new SALOME_PYQT_DataObjectLight and return its entry*/
   QString                   createObject(const QString& parent);
@@ -193,6 +193,7 @@ private:
   void                       connectView( const SUIT_ViewWindow* );
 
   void                       saveEvent(QStringList& theListOfFiles);
+  void                       dumpEvent(QStringList& theListOfFiles);
   void                       openEvent(QStringList theListOfFiles, bool& opened);
 
   SALOME_PYQT_DataObjectLight* findObject(const QString& entry);
index 97c8c1590d0ab8f2411e4f1899ed8f57039eda0f..3ac65184b47270585edae72a70d2b292033c9d50 100644 (file)
@@ -812,21 +812,10 @@ void SalomeApp_Application::onDumpStudy( )
       QFileInfo aFileInfo(aFileName);
       if( aFileInfo.isDir() ) // IPAL19257
         return;
+      
+      // Issue 21377 - dump study implementation moved to SalomeApp_Study class
+      bool res = appStudy->dump( aFileName, toPublish, isMultiFile, toSaveGUI );
 
-      int savePoint;
-      _PTR(AttributeParameter) ap;
-      _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
-      if(ip->isDumpPython(appStudy->studyDS())) ip->setDumpPython(appStudy->studyDS()); //Unset DumpPython flag.
-      if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
-        ip->setDumpPython(appStudy->studyDS());
-        savePoint = SalomeApp_VisualState( this ).storeState(); //SRN: create a temporary save point
-      }
-      bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toStdString(),
-                                    aFileInfo.baseName().toStdString(),
-                                    toPublish,
-                                    isMultiFile);
-      if ( toSaveGUI )
-        appStudy->removeSavePoint(savePoint); //SRN: remove the created temporary save point.
       if ( !res )
         SUIT_MessageBox::warning( desktop(),
                                   QObject::tr("WRN_WARNING"),
@@ -1222,20 +1211,6 @@ SALOME_LifeCycleCORBA* SalomeApp_Application::lcc()
   return &_lcc;
 }
 
-/*!Return default engine IOR for light modules*/
-QString SalomeApp_Application::defaultEngineIOR()
-{
-  /// Look for a default module engine (needed for CORBAless modules to use SALOMEDS persistence)
-  QString anIOR( "" );
-  CORBA::Object_ptr anEngine = namingService()->Resolve( "/SalomeAppEngine" );
-  if ( !CORBA::is_nil( anEngine ) )
-  {
-    CORBA::String_var objStr = orb()->object_to_string( anEngine );
-    anIOR = QString( objStr.in() );
-  }
-  return anIOR;
-}
-
 /*!Private SLOT. On preferences.*/
 void SalomeApp_Application::onProperties()
 {
index aab013d665543e5503506b084de96e048fa40d0f..711333875937697df5e72ed0fff7aa2640e07c56 100644 (file)
@@ -96,7 +96,6 @@ public:
   static SALOMEDSClient_StudyManager* studyMgr();
   static SALOME_NamingService*        namingService();
   static SALOME_LifeCycleCORBA*       lcc();
-  static QString                      defaultEngineIOR();
 
   SUIT_ViewManager*                   newViewManager(const QString&);
   void                                updateSavePointDataObjects( SalomeApp_Study* );
index 2972f8added833377faad21858069b00b13cf757..a7ffd3538e323d4a364078e11d7c4a23046c9529 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <QCoreApplication>
 #include <QEvent>
+#include <QFileInfo>
 #include "SALOME_Event.h"
 #include "Basics_Utils.hxx"
 
@@ -503,7 +504,10 @@ bool SalomeApp_Study::saveDocumentAs( const QString& theFileName )
   QListIterator<CAM_DataModel*> it( list );
   QStringList listOfFiles;
   while ( it.hasNext() ) {
-    if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() ) {
+    // Cast to LightApp class in order to give a chance
+    // to light modules to save their data
+    if ( LightApp_DataModel* aModel = 
+        dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
       listOfFiles.clear();
       aModel->saveAs( theFileName, this, listOfFiles );
       if ( !listOfFiles.isEmpty() )
@@ -545,7 +549,10 @@ bool SalomeApp_Study::saveDocument()
   QListIterator<CAM_DataModel*> it( list );
   QStringList listOfFiles;
   while ( it.hasNext() ) {
-    if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() ) {
+    // Cast to LightApp class in order to give a chance
+    // to light modules to save their data
+    if ( LightApp_DataModel* aModel = 
+        dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
       listOfFiles.clear();
       aModel->save(listOfFiles);
       if ( !listOfFiles.isEmpty() ) 
@@ -590,6 +597,80 @@ void SalomeApp_Study::closeDocument(bool permanently)
   }
 }
 
+/*!
+  Dump study operation. Writes a Python dump file using
+  SALOMEDS services. Additionally, gives a chance to light modules
+  to participate in dump study operation.
+
+  \param theFileName - full path to the output Python file
+  \param toPublish - if true, all objects are published in a study 
+  by the output script, including those not orignally present 
+  in the current study.
+  \param isMultiFile - if true, each module's dump is written into 
+  a separate Python file, otherwise a single output file is written
+  \param toSaveGUI - if true, the GUI state is written
+
+  \return - true if the operation succeeds, and false otherwise.
+*/
+bool SalomeApp_Study::dump( const QString& theFileName, 
+                           bool toPublish, 
+                           bool isMultiFile,
+                           bool toSaveGUI )
+{
+  int savePoint;
+  _PTR(AttributeParameter) ap;
+  _PTR(IParameters) ip = ClientFactory::getIParameters(ap);
+  _PTR(Study) aStudy = studyDS();
+
+  if( ip->isDumpPython( aStudy ) ) 
+    ip->setDumpPython( aStudy ); //Unset DumpPython flag.
+
+  if ( toSaveGUI ) { //SRN: Store a visual state of the study at the save point for DumpStudy method
+    ip->setDumpPython( aStudy );
+    //SRN: create a temporary save point
+    savePoint = SalomeApp_VisualState( 
+      dynamic_cast<SalomeApp_Application*>( application() ) ).storeState(); 
+  }
+
+  // Issue 21377 - Each data model is asked to dump its data not present in SALOMEDS study.
+  // This is an optional but important step, it gives a chance to light modules
+  // to dump their data as a part of common dump study operation
+  ModelList list; 
+  dataModels( list );
+
+  QListIterator<CAM_DataModel*> it( list );
+  QStringList listOfFiles;
+  while ( it.hasNext() ) {
+    if ( LightApp_DataModel* aModel = 
+        dynamic_cast<LightApp_DataModel*>( it.next() ) ) {
+      listOfFiles.clear();
+      if ( aModel->dumpPython( theFileName, this, isMultiFile, listOfFiles ) && 
+          !listOfFiles.isEmpty() )
+       // This call simply passes the data model's dump output to SalomeApp_Engine servant.
+       // This code is shared with persistence mechanism.
+       // NOTE: this should be revised if behavior of saveModuleData() changes!
+        saveModuleData(aModel->module()->name(), listOfFiles);
+    }
+  }
+
+  // Now dump SALOMEDS part that also involves SalomeApp_Engine in case if 
+  // any light module is present in the current configuration
+  QFileInfo aFileInfo( theFileName );
+  bool res = aStudy->DumpStudy( aFileInfo.absolutePath().toStdString(),
+                               aFileInfo.baseName().toStdString(),
+                               toPublish,
+                               isMultiFile);
+  if ( toSaveGUI )
+    removeSavePoint( savePoint ); //SRN: remove the created temporary save point.
+
+  // Issue 21377 - Clean up light module data in SalomeApp_Engine servant
+  // This code is shared with persistence mechanism.
+  // NOTE: this should be revised if behavior of saveStudyData() changes!
+  saveStudyData( theFileName );
+
+  return res;
+}
+
 /*!
   \return true, if study is modified in comparison with last open/save
 */
@@ -667,16 +748,22 @@ void SalomeApp_Study::openModuleData( QString theModuleName, QStringList& theLis
 }
 
 /*!
-  Saves data from study
+  Re-implemented from LightApp_Study, actually does not save anything but
+  simply cleans up light modules' data
 */
 bool SalomeApp_Study::saveStudyData( const QString& theFileName )
 {
   ModelList list; dataModels( list );
   QListIterator<CAM_DataModel*> it( list );
   std::vector<std::string> listOfFiles(0);
-  while ( it.hasNext() )
-    if ( SalomeApp_DataModel* aModel = (SalomeApp_DataModel*)it.next() )
-      SetListOfFiles(aModel->module()->name().toStdString().c_str(), listOfFiles);
+  while ( it.hasNext() ){
+    LightApp_DataModel* aLModel = 
+      dynamic_cast<LightApp_DataModel*>( it.next() );
+    // It is safe to call SetListOfFiles() for any kind of module
+    // because SetListOfFiles() does nothing for full modules :)
+    if ( aLModel )
+      SetListOfFiles(aLModel->module()->name().toStdString().c_str(), listOfFiles);
+  }
   return true;
 }
 
@@ -735,7 +822,7 @@ CAM_ModuleObject* SalomeApp_Study::createModuleObject( LightApp_DataModel* theDa
 
     _PTR(SComponent) aComp = aStudy->FindComponent( 
       theDataModel->module()->name().toStdString() );
-    if ( aComp )
+    if ( !aComp )
       return res;
 
     res = new SalomeApp_ModuleObject( theDataModel, aComp, theParent );
@@ -768,11 +855,14 @@ void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
     _PTR(Study) aStudy = studyDS();
     if (!aStudy) 
       return;
-    _PTR(SComponent) aComp = aStudy->FindComponent(dm->module()->name().toStdString());
+
+    std::string aCompDataType = dm->module()->name().toStdString();
+
+    _PTR(SComponent) aComp = aStudy->FindComponent(aCompDataType);
     if (!aComp) {
       // Create SComponent
       _PTR(StudyBuilder) aBuilder = aStudy->NewBuilder();
-      aComp = aBuilder->NewComponent(dm->module()->name().toStdString());
+      aComp = aBuilder->NewComponent(aCompDataType);
       aBuilder->SetName(aComp, dm->module()->moduleName().toStdString());
       QString anIconName = dm->module()->iconName();
       if (!anIconName.isEmpty()) {
@@ -780,8 +870,12 @@ void SalomeApp_Study::addComponent(const CAM_DataModel* dm)
         if (anAttr)
           anAttr->SetPixMap(anIconName.toStdString());
       }
+
       // Set default engine IOR
-      aBuilder->DefineComponentInstance(aComp, SalomeApp_Application::defaultEngineIOR().toStdString());
+      // Issue 21377 - using separate engine for each type of light module
+      std::string anEngineIOR = SalomeApp_Engine_i::EngineIORForComponent( aCompDataType.c_str(),
+                                                                          true );
+      aBuilder->DefineComponentInstance(aComp, anEngineIOR);
       //SalomeApp_DataModel::BuildTree( aComp, root(), this, /*skipExisitng=*/true );
       SalomeApp_DataModel::synchronize( aComp, this );
     }
@@ -803,8 +897,10 @@ bool SalomeApp_Study::openDataModel( const QString& studyName, CAM_DataModel* dm
   QString anEngine;
   // 1. aModule == 0 means that this is a light module (no CORBA enigine)
   if (!aModule) {
-    anEngine = SalomeApp_Application::defaultEngineIOR();
-    aSComp = aStudy->FindComponent(dm->module()->name().toStdString());
+    // Issue 21377 - using separate engine for each type of light module
+    std::string aCompDataType = dm->module()->name().toStdString();
+    anEngine = SalomeApp_Engine_i::EngineIORForComponent( aCompDataType.c_str(), true ).c_str();
+    aSComp = aStudy->FindComponent( aCompDataType );
   }
   else {
     SalomeApp_DataModel* aDM = dynamic_cast<SalomeApp_DataModel*>( dm );
@@ -876,30 +972,38 @@ QString SalomeApp_Study::newStudyName() const
 }
 
 /*!
+  Note that this method does not create or activate SalomeApp_Engine_i instance,
+  therefore it can be called safely for any kind of module, but for full
+  modules it returns an empty list.
   \return list of files used by module: to be used by CORBAless modules
   \param theModuleName - name of module
 */
 std::vector<std::string> SalomeApp_Study::GetListOfFiles( const char* theModuleName  ) const
 {
-  SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
+  // Issue 21377 - using separate engine for each type of light module
+  SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
   if (aDefaultEngine)
-    return aDefaultEngine->GetListOfFiles(id(), theModuleName);
+    return aDefaultEngine->GetListOfFiles(id());
 
   std::vector<std::string> aListOfFiles;
   return aListOfFiles;
 }
 
 /*!
-  Sets list of files used by module: to be used by CORBAless modules
+  Sets list of files used by module: to be used by CORBAless modules.
+  Note that this method does not create or activate SalomeApp_Engine_i instance,
+  therefore it can be called safely for any kind of module, but for full
+  modules it simply does nothing.
   \param theModuleName - name of module
   \param theListOfFiles - list of files
 */
 void SalomeApp_Study::SetListOfFiles ( const char* theModuleName,
                                        const std::vector<std::string> theListOfFiles )
 {
-  SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance();
+  // Issue 21377 - using separate engine for each type of light module
+  SalomeApp_Engine_i* aDefaultEngine = SalomeApp_Engine_i::GetInstance( theModuleName, false );
   if (aDefaultEngine)
-    aDefaultEngine->SetListOfFiles(theListOfFiles, id(), theModuleName);
+    aDefaultEngine->SetListOfFiles(theListOfFiles, id());
 }
 
 /*!
index 41ebe37153a84c957280209e8eab582ae0054028..2487cd5def1f746030d135a1d4270e6c37baf9b2 100644 (file)
@@ -55,6 +55,8 @@ public:
 
   virtual void        closeDocument(bool permanently = true);
 
+  virtual bool        dump( const QString&, bool, bool, bool );
+
   virtual bool        isSaved()  const;
   virtual bool        isModified() const;
   virtual void        Modified();
index 639d3e84f222306c1271936d2b367d5cfcc1fdc9..c31e83fb34064d17dd9ce40949087b41a202d9e5 100644 (file)
 //
 #include "SalomeApp_Engine_i.hxx"
 
-#include "SALOMEDS_Tool.hxx"
+#include <SALOME_NamingService.hxx>
+#include <SALOMEDS_Tool.hxx>
+#include <Utils_ORB_INIT.hxx>
+#include <Utils_SINGLETON.hxx>
+#include <Utils_SALOME_Exception.hxx>
+#include <utilities.h>
+
+#include <QApplication>
+#include <QDir>
+#include <QFile>
 
 #include <iostream>
 
 using namespace std;
 
-SalomeApp_Engine_i* SalomeApp_Engine_i::myInstance = NULL;
-
 /*!
   Constructor
 */
-SalomeApp_Engine_i::SalomeApp_Engine_i()
+SalomeApp_Engine_i::SalomeApp_Engine_i( const char* theComponentName )
 {
-  myInstance = this;
+  myComponentName = theComponentName;
+  MESSAGE("SalomeApp_Engine_i::SalomeApp_Engine_i(): myComponentName = "<<
+         myComponentName << ", this = " << this);
 }
 
 /*!
@@ -49,6 +58,8 @@ SalomeApp_Engine_i::SalomeApp_Engine_i()
 */
 SalomeApp_Engine_i::~SalomeApp_Engine_i()
 {
+  MESSAGE("SalomeApp_Engine_i::~SalomeApp_Engine_i(): myComponentName = " << myComponentName <<
+         myComponentName << ", this = " << this);
 }
 
 SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theComponent,
@@ -57,22 +68,23 @@ SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theCompone
 {
   SALOMEDS::TMPFile_var aStreamFile = new SALOMEDS::TMPFile;
 
-  cout << "SalomeApp_Engine_i::Save() isMultiFile = " << isMultiFile << endl;
   if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy()))
     return aStreamFile._retn();
 
   const int studyId = theComponent->GetStudy()->StudyId();
-  cout << "SalomeApp_Engine_i::Save() - studyId = " << studyId << endl;
 
   // Get a temporary directory to store a file
   //std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
 
   if (myMap.count(studyId)) {
-    cout << "SalomeApp_Engine_i::Save() - myMap.count(studyId)" << endl;
-    MapOfListOfFiles mapOfListOfFiles = myMap[studyId];
     std::string componentName (theComponent->ComponentDataType());
-    cout << "SalomeApp_Engine_i::Save() - componentName = " << componentName << endl;
-    ListOfFiles listOfFiles = mapOfListOfFiles[componentName];
+
+    // Error somewhere outside - Save() called with
+    // wrong SComponent instance
+    if ( myComponentName != componentName )
+      return aStreamFile._retn();
+
+    const ListOfFiles& listOfFiles = myMap[studyId];
 
     // listOfFiles must contain temporary directory name in its first item
     // and names of files (relatively the temporary directory) in the others
@@ -80,7 +92,6 @@ SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theCompone
 
     if (n > 0) { // there are some files, containing persistent data of the component
       std::string aTmpDir = listOfFiles[0];
-      cout << "SalomeApp_Engine_i::Save() - aTmpDir = " << aTmpDir << endl;
 
       // Create a list to store names of created files
       SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
@@ -108,6 +119,12 @@ CORBA::Boolean SalomeApp_Engine_i::Load (SALOMEDS::SComponent_ptr theComponent,
   if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy()))
     return false;
 
+  // Error somewhere outside - Load() called with
+  // wrong SComponent instance
+  std::string componentName (theComponent->ComponentDataType());
+  if ( myComponentName != componentName )
+    return false;
+
   const int studyId = theComponent->GetStudy()->StudyId();
 
   // Create a temporary directory for the component's data files
@@ -125,52 +142,259 @@ CORBA::Boolean SalomeApp_Engine_i::Load (SALOMEDS::SComponent_ptr theComponent,
   for (int i = 1; i < n; i++)
     listOfFiles[i] = std::string(aSeq[i - 1]);
 
-  //MapOfListOfFiles mapOfListOfFiles;
-  //if (myMap.count(studyId))
-  //  mapOfListOfFiles = myMap[studyId];
-  //std::string componentName (theComponent->ComponentDataType());
-  //mapOfListOfFiles[componentName] = listOfFiles;
-  //myMap[studyId] = mapOfListOfFiles;
-
-  SetListOfFiles(listOfFiles, studyId, theComponent->ComponentDataType());
+  SetListOfFiles(listOfFiles, studyId);
 
   return true;
 }
 
-SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles (const int theStudyId,
-                                                                    const char* theComponentName)
+SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles (const int theStudyId)
 {
   ListOfFiles aListOfFiles;
 
-  if (myMap.count(theStudyId))
+  if (myMap.find(theStudyId) != myMap.end())
   {
-    MapOfListOfFiles mapOfListOfFiles = myMap[theStudyId];
-    std::string componentName (theComponentName);
-    if (mapOfListOfFiles.count(componentName))
-      aListOfFiles = mapOfListOfFiles[componentName];
+    aListOfFiles = myMap[theStudyId];
   }
 
   return aListOfFiles;
 }
 
-void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles theListOfFiles,
-                                         const int   theStudyId,
-                                         const char* theComponentName)
+void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles& theListOfFiles,
+                                         const int          theStudyId)
 {
-  //if (!myMap.count(theStudyId)) {
-  //  MapOfListOfFiles mapOfListOfFiles;
-  //  myMap[theStudyId] = mapOfListOfFiles;
-  //}
-
-  MapOfListOfFiles& mapOfListOfFiles = myMap[theStudyId];
-  std::string componentName (theComponentName);
-  mapOfListOfFiles[componentName] = theListOfFiles;
+  myMap[theStudyId] = theListOfFiles;
+}
+
+/*! 
+ *  DumpPython implementation for light modules
+ */
+Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Object_ptr theStudy, 
+                                                CORBA::Boolean isPublished, 
+                                                CORBA::Boolean isMultiFile, 
+                                                CORBA::Boolean& isValidScript)
+{
+  MESSAGE("SalomeApp_Engine_i::DumpPython(): myComponentName = "<<
+         myComponentName << ", this = " << this);
+  
+  // Temporary solution: returning a non-empty sequence
+  // even if there's nothing to dump, to avoid crashes in SALOMEDS
+  // TODO: Improve SALOMEDSImpl_Study::DumpStudy() by skipping the components 
+  // with isValidScript == false, and initialize isValidScript by false below.
+  Engines::TMPFile_var aStreamFile = new Engines::TMPFile(1);
+  aStreamFile->length( 1 );
+  aStreamFile[0] = '\0';
+  isValidScript = true;
+
+  if (CORBA::is_nil(theStudy))
+    return aStreamFile._retn();
+
+  SALOMEDS::Study_var studyDS = SALOMEDS::Study::_narrow( theStudy );
+  const int studyId = studyDS->StudyId();
+
+  if (!myMap.count(studyId))
+    return aStreamFile._retn();
+
+  ListOfFiles listOfFiles = myMap[studyId];
+
+  // listOfFiles must contain temporary directory name in its first item
+  // and names of files (relatively the temporary directory) in the others
+  if ( listOfFiles.size() < 2 ) 
+    return aStreamFile._retn();
+
+  // there are some files, containing persistent data of the component
+  QString aTmpPath( listOfFiles.front().c_str() );
+  QDir aTmpDir( aTmpPath );
+  if ( !aTmpDir.exists() )
+    return aStreamFile._retn();    
+
+  // Calculate file sizes
+  QStringList aFilePaths;
+  QList<qint64> aFileSizes;
+  qint64 aBuffSize = 0;
+  ListOfFiles::const_iterator aFIt  = listOfFiles.begin();
+  ListOfFiles::const_iterator aFEnd = listOfFiles.end();
+  aFIt++;
+  for (; aFIt != aFEnd; aFIt++){
+    QString aFileName( (*aFIt).c_str() );
+    if ( !aTmpDir.exists( aFileName ) ){
+      continue;
+    }
+
+    QFile aFile( aTmpDir.filePath( aFileName ) );
+    if ( !aFile.open( QIODevice::ReadOnly ) ){
+      continue;
+    }
+
+    aFilePaths.push_back( aTmpDir.filePath( aFileName ) );
+    aFileSizes.push_back( aFile.size() );
+    aBuffSize += aFileSizes.back();
+
+    aFile.close();
+  }
+
+  if ( !aFilePaths.size() || !aBuffSize )
+    return aStreamFile._retn(); 
+    
+  char* aBuffer = new char[aBuffSize + 1];
+  if ( !aBuffer )
+    return aStreamFile._retn();
+
+  // Convert the file(s) to the byte stream, multiple files are simply
+  // concatenated
+  // TODO: imporve multi-script support if necessary...
+  qint64 aCurrPos = 0;
+  QStringList::const_iterator aFileIt  = aFilePaths.begin();
+  QStringList::const_iterator aFileEnd = aFilePaths.end();
+  QList<qint64>::const_iterator   aSIt = aFileSizes.begin();
+  for ( ; aFileIt != aFileEnd; aFileIt++, aSIt++ ){
+    QFile aFile( aTmpDir.filePath( *aFileIt ) );
+    if ( !aFile.open( QIODevice::ReadOnly ) ){
+      continue;
+    }
+
+    // Incorrect size of file
+    // Do not remove the bad file to have some diagnostic means
+    if ( aFile.read( aBuffer + aCurrPos, *aSIt ) != *aSIt ){
+      aFile.close();      
+      return aStreamFile._retn();
+    }
+
+    aCurrPos += (*aSIt); 
+    aFile.remove();   
+  }
+
+  // Here we should end up with empty aTmpDir
+  // TODO: Handle QDir::rmdir() error status somehow...
+  aTmpDir.rmdir( aTmpPath );
+
+  aBuffer[aBuffSize] = '\0';
+  CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
+  aStreamFile = new Engines::TMPFile(aBuffSize + 1, aBuffSize + 1, anOctetBuf, 1); 
+
+  return aStreamFile._retn();
 }
 
 /*!
-  \return shared instance of engine
+  \return Component data type string for this instance of the engine
 */
-SalomeApp_Engine_i* SalomeApp_Engine_i::GetInstance()
+char* SalomeApp_Engine_i::ComponentDataType()
 {
-  return myInstance;
+  return const_cast<char*>( myComponentName.c_str() );
 }
+
+/*!
+  \return 
+*/
+CORBA::ORB_var SalomeApp_Engine_i::orb()
+{
+  ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
+  // TODO: using QApplication here looks ugly, think how to
+  // obtain the ORB reference in a nicer way...
+  static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
+  return _orb;
+}
+
+/*!
+  \return 
+*/
+PortableServer::POA_var SalomeApp_Engine_i::poa()
+{
+  static PortableServer::POA_var _poa;
+  if ( CORBA::is_nil( _poa ) ){
+    CORBA::Object_var obj = orb()->resolve_initial_references( "RootPOA" );
+    _poa = PortableServer::POA::_narrow( obj );
+  }
+  return _poa;
+}
+
+/*!
+  \return 
+*/
+SALOME_NamingService* SalomeApp_Engine_i::namingService()
+{
+  static SALOME_NamingService _ns(orb());
+  return &_ns;
+}
+
+/*!
+  Internal method, creates a CORBA engine for a light SALOME module
+  with the given "component data type" string,
+  activates it and registers in SALOME naming service with
+  /SalomeAppEngine/comp_data_type path. If the engine is already in the 
+  naming service, simply returns and object reference to it.
+  \param theComponentName - synthetic "component data type" used to identify a given light module
+  \return Object reference to the CORBA engine
+*/
+CORBA::Object_ptr SalomeApp_Engine_i::engineForComponent( const char* theComponentName,
+                                                         bool toCreate )
+{
+  CORBA::Object_var anEngine;
+  if ( !theComponentName || !strlen( theComponentName ) )
+    return anEngine._retn();
+
+  std::string aPath( "/SalomeAppEngine/" );
+  aPath += theComponentName;
+  anEngine = namingService()->Resolve( aPath.c_str() );
+
+  // Activating a new instance of the servant
+  if ( toCreate && CORBA::is_nil( anEngine ) ){
+    try {
+      SalomeApp_Engine_i* aServant    = new SalomeApp_Engine_i( theComponentName );
+      PortableServer::ObjectId_var id = poa()->activate_object( aServant );
+      anEngine = aServant->_this();
+      aServant->_remove_ref();
+      namingService()->Register( anEngine.in(), aPath.c_str() );
+    }
+    catch (CORBA::SystemException&) {
+      INFOS("Caught CORBA::SystemException.");
+    }
+    catch (CORBA::Exception&) {
+      INFOS("Caught CORBA::Exception.");
+    }
+    catch (...) {
+      INFOS("Caught unknown exception.");
+    }
+  }
+
+  return anEngine._retn();
+}
+
+/*!
+  \param theComponentName - synthetic "component data type" used to identify a given light module
+  \return IOR string for the CORBA engine for a light SALOME module
+  with the given "component data type" string
+  \sa GetInstance( const char* theComponentName )
+*/
+std::string SalomeApp_Engine_i::EngineIORForComponent( const char* theComponentName,
+                                                      bool toCreate )
+{
+  std::string anIOR( "" );
+  CORBA::Object_var anEngine = engineForComponent( theComponentName, toCreate );
+  if ( !CORBA::is_nil( anEngine ) )
+  {
+    CORBA::String_var objStr = orb()->object_to_string( anEngine.in() );
+    anIOR = std::string( objStr.in() );
+  }
+  return anIOR;
+}
+
+/*!
+  \param theComponentName - synthetic "component data type" used to identify a given light module
+  \return A pointer to corresponding C++ engine instance, null means some internal problems.
+  \sa EngineIORForComponent( const char* theComponentName )
+*/
+SalomeApp_Engine_i* SalomeApp_Engine_i::GetInstance( const char* theComponentName,
+                                                    bool toCreate )
+{
+  SalomeApp_Engine_i* aServant = 0;
+  CORBA::Object_var anEngine = engineForComponent( theComponentName, toCreate );
+  if ( !CORBA::is_nil( anEngine ) )
+  {
+    PortableServer::Servant aServantBase = poa()->reference_to_servant( anEngine.in() );
+    aServant = dynamic_cast<SalomeApp_Engine_i*>( aServantBase );
+  } 
+  MESSAGE("SalomeApp_Engine_i::GetInstance(): theComponentName = " <<
+         theComponentName << ", aServant = " << aServant);
+  return aServant;
+}
+
index 965f46b9c6d5d390d843c0a36ca880692c463d0e..e9030cbb7bc57bbf6a1507ac6a9c37a84a473219 100755 (executable)
 #include <SALOMEconfig.h>
 #include CORBA_SERVER_HEADER(SalomeApp_Engine)
 
+class SALOME_NamingService;
+
 class SESSION_EXPORT SalomeApp_Engine_i: public POA_SalomeApp::Engine,
-                          public Engines_Component_i
+                                        public Engines_Component_i
 {
 public:
-  SalomeApp_Engine_i();
+  SalomeApp_Engine_i( const char* theComponentName );
   ~SalomeApp_Engine_i();
 
   SALOMEDS::TMPFile*      Save( SALOMEDS::SComponent_ptr theComponent, 
@@ -55,17 +57,22 @@ public:
                                const char* theURL, 
                                bool isMultiFile );
 
+  virtual Engines::TMPFile* DumpPython(CORBA::Object_ptr theStudy,
+                                       CORBA::Boolean isPublished,
+                                       CORBA::Boolean isMultiFile,
+                                       CORBA::Boolean& isValidScript);
+
 public:
   typedef std::vector<std::string> ListOfFiles;
 
-  ListOfFiles             GetListOfFiles (const int         theStudyId, 
-                                          const char*       theComponentName);
-
-  void                    SetListOfFiles (const ListOfFiles theListOfFiles,
-                                          const int         theStudyId, 
-                                          const char*       theComponentName);
+  ListOfFiles             GetListOfFiles (const int          theStudyId);
+  void                    SetListOfFiles (const ListOfFiles& theListOfFiles,
+                                          const int          theStudyId);
 
-  static SalomeApp_Engine_i* GetInstance();
+  static std::string         EngineIORForComponent( const char* theComponentName,
+                                                   bool toCreate );
+  static SalomeApp_Engine_i* GetInstance          ( const char* theComponentName,
+                                                   bool toCreate ); 
 
 public:
   // methods from SALOMEDS::Driver without implementation.  Must be redefined because 
@@ -73,7 +80,7 @@ public:
   SALOMEDS::TMPFile* SaveASCII( SALOMEDS::SComponent_ptr, const char*, bool )                                                                        {return 0;}
   CORBA::Boolean LoadASCII( SALOMEDS::SComponent_ptr, const SALOMEDS::TMPFile&, const char*, bool )                                                  {return 0;}
   void Close( SALOMEDS::SComponent_ptr )                                                                                                             {}
-  char* ComponentDataType()                                                                                                                          {return 0;}
+  char* ComponentDataType();
   char* IORToLocalPersistentID( SALOMEDS::SObject_ptr, const char*, CORBA::Boolean,  CORBA::Boolean )                                                {return 0;}
   char* LocalPersistentIDToIOR( SALOMEDS::SObject_ptr, const char*, CORBA::Boolean,  CORBA::Boolean )                                                {return 0;}
   bool CanPublishInStudy( CORBA::Object_ptr )                                                                                                        {return 0;}
@@ -84,11 +91,17 @@ public:
   SALOMEDS::SObject_ptr PasteInto( const SALOMEDS::TMPFile&, CORBA::Long, SALOMEDS::SObject_ptr )                                                    {return 0;}
 
 private:
-  typedef std::map<std::string, ListOfFiles> MapOfListOfFiles;
-  typedef std::map<int, MapOfListOfFiles>    MapOfMapOfListOfFiles;
-  MapOfMapOfListOfFiles                      myMap;
+  static CORBA::ORB_var              orb();
+  static PortableServer::POA_var     poa();
+  static SALOME_NamingService*       namingService();
+  static CORBA::Object_ptr           engineForComponent( const char* theComponentName,
+                                                        bool toCreate  );
+
+private:
+  typedef std::map<int, ListOfFiles> MapOfListOfFiles;
+  MapOfListOfFiles                   myMap;
 
-  static SalomeApp_Engine_i* myInstance;
+  std::string                        myComponentName;
 };
 
 #endif
index df8422f8f811af7208aec9cc78691673ecb656b7..71a8503aac2f7efcfe8f4e6bb8116a315910bdd0 100755 (executable)
@@ -127,6 +127,17 @@ void Session_ServerLauncher::CheckArgs()
           }
         case 1: // looking for server type
           {
+           // Temporary solution
+           // Issue 21337 - no more SalomeApp_Engine_i activation here
+           // TODO: To be removed as soon as any trace of SalomeAppEngine
+           // has been eliminated from KERNEL scripts
+           if (strcmp(_argv[iarg], "SalomeAppEngine")==0){
+             argState = 0;
+             iarg += 2; // skipping "()" 
+             break;
+           }
+           // Temporary solution
+
             for (int i=0; i<Session_ServerThread::NB_SRV_TYP; i++)
                 if (strcmp(_argv[iarg],Session_ServerThread::_serverTypes[i])==0)
                   {
index ff3282e66927a1cdb62ebc449caaddfec05c6d8d..d158208480344dee71d10bcc398d7a5229bd4c16 100755 (executable)
@@ -39,7 +39,6 @@
 #include <RegistryService.hxx>
 
 #include "Session_Session_i.hxx"
-#include "SalomeApp_Engine_i.hxx"
 
 #include <Utils_ORB_INIT.hxx>
 #include <Utils_SINGLETON.hxx>
 
 using namespace std;
 
-const int Session_ServerThread::NB_SRV_TYP = 7;
+const int Session_ServerThread::NB_SRV_TYP = 6;
 const char* Session_ServerThread::_serverTypes[NB_SRV_TYP] = {"Container",
                                                               "ModuleCatalog",
                                                               "Registry",
                                                               "SALOMEDS",
                                                               "Session",
-                                                              "SalomeAppEngine",
                                                               "ContainerManager"};
 
 /*! 
@@ -158,13 +156,7 @@ void Session_ServerThread::Init()
           ActivateSession(_argc, _argv);
           break;
         }
-      case 5: // SalomeApp_Engine
-        {
-          NamingService_WaitForServerReadiness(_NS,"/myStudyManager");
-          ActivateEngine(_argc, _argv);
-          break;
-        }
-      case 6: // Container Manager
+      case 5: // Container Manager
         {
           NamingService_WaitForServerReadiness(_NS,"");
           ActivateContainerManager(_argc, _argv);
@@ -390,29 +382,6 @@ void Session_ServerThread::ActivateContainer(int argc,
   }
 }
 
-void Session_ServerThread::ActivateEngine(int /*argc*/, char ** /*argv*/)
-{
-  try {
-    MESSAGE("SalomeApp_Engine thread started");
-    SalomeApp_Engine_i* anEngine = new SalomeApp_Engine_i();
-    PortableServer::ObjectId_var id =_root_poa->activate_object( anEngine );
-    MESSAGE("poa->activate_object( SalomeApp_Engine )");
-
-    CORBA::Object_var obj = anEngine->_this();
-    anEngine->_remove_ref();
-    _NS->Register( obj ,"/SalomeAppEngine");
-  }
-  catch (CORBA::SystemException&) {
-    INFOS("Caught CORBA::SystemException.");
-  }
-  catch (CORBA::Exception&) {
-    INFOS("Caught CORBA::Exception.");
-  }
-  catch (...) {
-    INFOS("Caught unknown exception.");
-  }
-}
-
 void Session_ServerThread::ActivateSession(int argc,
                                            char ** argv)
 {