Back to index

salome-gui  6.5.0
SalomeApp_Engine_i.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SalomeApp_Engine_i : implementation of SalomeApp_Engine.idl
00024 //  File   : SalomeApp_Engine_i.cxx
00025 //  Author : Alexander SLADKOV
00026 
00027 #include "SalomeApp_Engine_i.hxx"
00028 
00029 #include <SALOME_NamingService.hxx>
00030 #include <SALOMEDS_Tool.hxx>
00031 #include <Utils_ORB_INIT.hxx>
00032 #include <Utils_SINGLETON.hxx>
00033 #include <Utils_SALOME_Exception.hxx>
00034 #include <utilities.h>
00035 
00036 #include <QApplication>
00037 #include <QDir>
00038 #include <QFile>
00039 
00040 #include <iostream>
00041 
00045 SalomeApp_Engine_i::SalomeApp_Engine_i( const char* theComponentName )
00046 {
00047   myComponentName = theComponentName;
00048   MESSAGE("SalomeApp_Engine_i::SalomeApp_Engine_i(): myComponentName = " <<
00049          myComponentName << ", this = " << this);
00050 }
00051 
00055 SalomeApp_Engine_i::~SalomeApp_Engine_i()
00056 {
00057   MESSAGE("SalomeApp_Engine_i::~SalomeApp_Engine_i(): myComponentName = " << 
00058          myComponentName << ", this = " << this);
00059 }
00060 
00061 SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theComponent,
00062                                              const char* theURL,
00063                                              bool isMultiFile)
00064 {
00065   SALOMEDS::TMPFile_var aStreamFile = new SALOMEDS::TMPFile;
00066 
00067   if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy()))
00068     return aStreamFile._retn();
00069 
00070   const int studyId = theComponent->GetStudy()->StudyId();
00071 
00072   // Get a temporary directory to store a file
00073   //std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
00074 
00075   if (myMap.count(studyId)) {
00076     std::string componentName (theComponent->ComponentDataType());
00077 
00078     // Error somewhere outside - Save() called with
00079     // wrong SComponent instance
00080     if ( myComponentName != componentName )
00081       return aStreamFile._retn();
00082 
00083     const ListOfFiles& listOfFiles = myMap[studyId];
00084 
00085     // listOfFiles must contain temporary directory name in its first item
00086     // and names of files (relatively the temporary directory) in the others
00087     const int n = listOfFiles.size() - 1;
00088 
00089     if (n > 0) { // there are some files, containing persistent data of the component
00090       std::string aTmpDir = listOfFiles[0];
00091 
00092       // Create a list to store names of created files
00093       SALOMEDS::ListOfFileNames_var aSeq = new SALOMEDS::ListOfFileNames;
00094       aSeq->length(n);
00095       for (int i = 0; i < n; i++)
00096         aSeq[i] = CORBA::string_dup(listOfFiles[i + 1].c_str());
00097 
00098       // Convert a file to the byte stream
00099       aStreamFile = SALOMEDS_Tool::PutFilesToStream(aTmpDir.c_str(), aSeq.in(), isMultiFile);
00100 
00101       // Remove the files and tmp directory, created by the component storage procedure
00102       if (!isMultiFile) SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq.in(), true);
00103     }
00104   }
00105 
00106   return aStreamFile._retn();
00107 }
00108 
00109 CORBA::Boolean SalomeApp_Engine_i::Load (SALOMEDS::SComponent_ptr theComponent,
00110                                          const SALOMEDS::TMPFile& theFile,
00111                                          const char* theURL,
00112                                          bool isMultiFile)
00113 {
00114   std::cout << "SalomeApp_Engine_i::Load() isMultiFile = " << isMultiFile << std::endl;
00115   if (CORBA::is_nil(theComponent) || CORBA::is_nil(theComponent->GetStudy()))
00116     return false;
00117 
00118   // Error somewhere outside - Load() called with
00119   // wrong SComponent instance
00120   std::string componentName (theComponent->ComponentDataType());
00121   if ( myComponentName != componentName )
00122     return false;
00123 
00124   const int studyId = theComponent->GetStudy()->StudyId();
00125 
00126   // Create a temporary directory for the component's data files
00127   std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
00128 
00129   // Convert the byte stream theStream to a files and place them in the tmp directory.
00130   // The files and temporary directory must be deleted by the component loading procedure.
00131   SALOMEDS::ListOfFileNames_var aSeq =
00132     SALOMEDS_Tool::PutStreamToFiles(theFile, aTmpDir.c_str(), isMultiFile);
00133 
00134   // Store list of file names to be used by the component loading procedure
00135   const int n = aSeq->length() + 1;
00136   ListOfFiles listOfFiles (n);
00137   listOfFiles[0] = aTmpDir;
00138   for (int i = 1; i < n; i++)
00139     listOfFiles[i] = std::string(aSeq[i - 1]);
00140 
00141   SetListOfFiles(listOfFiles, studyId);
00142 
00143   return true;
00144 }
00145 
00146 SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles (const int theStudyId)
00147 {
00148   ListOfFiles aListOfFiles;
00149 
00150   if (myMap.find(theStudyId) != myMap.end())
00151   {
00152     aListOfFiles = myMap[theStudyId];
00153   }
00154 
00155   return aListOfFiles;
00156 }
00157 
00158 void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles& theListOfFiles,
00159                                          const int          theStudyId)
00160 {
00161   myMap[theStudyId] = theListOfFiles;
00162 }
00163 
00167 Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Object_ptr theStudy, 
00168                                            CORBA::Boolean isPublished, 
00169                                            CORBA::Boolean isMultiFile, 
00170                                            CORBA::Boolean& isValidScript)
00171 {
00172   MESSAGE("SalomeApp_Engine_i::DumpPython(): myComponentName = "<<
00173          myComponentName << ", this = " << this);
00174   
00175   // Temporary solution: returning a non-empty sequence
00176   // even if there's nothing to dump, to avoid crashes in SALOMEDS
00177   // TODO: Improve SALOMEDSImpl_Study::DumpStudy() by skipping the components 
00178   // with isValidScript == false, and initialize isValidScript by false below.
00179   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(1);
00180   aStreamFile->length( 1 );
00181   aStreamFile[0] = '\0';
00182   isValidScript = true;
00183 
00184   if (CORBA::is_nil(theStudy))
00185     return aStreamFile._retn();
00186 
00187   SALOMEDS::Study_var studyDS = SALOMEDS::Study::_narrow( theStudy );
00188   const int studyId = studyDS->StudyId();
00189 
00190   if (!myMap.count(studyId))
00191     return aStreamFile._retn();
00192 
00193   ListOfFiles listOfFiles = myMap[studyId];
00194 
00195   // listOfFiles must contain temporary directory name in its first item
00196   // and names of files (relatively the temporary directory) in the others
00197   if ( listOfFiles.size() < 2 ) 
00198     return aStreamFile._retn();
00199 
00200   // there are some files, containing persistent data of the component
00201   QString aTmpPath( listOfFiles.front().c_str() );
00202   QDir aTmpDir( aTmpPath );
00203   if ( !aTmpDir.exists() )
00204     return aStreamFile._retn();    
00205 
00206   // Calculate file sizes
00207   QStringList aFilePaths;
00208   QList<qint64> aFileSizes;
00209   qint64 aBuffSize = 0;
00210   ListOfFiles::const_iterator aFIt  = listOfFiles.begin();
00211   ListOfFiles::const_iterator aFEnd = listOfFiles.end();
00212   aFIt++;
00213   for (; aFIt != aFEnd; aFIt++){
00214     QString aFileName( (*aFIt).c_str() );
00215     if ( !aTmpDir.exists( aFileName ) ){
00216       continue;
00217     }
00218 
00219     QFile aFile( aTmpDir.filePath( aFileName ) );
00220     if ( !aFile.open( QIODevice::ReadOnly ) ){
00221       continue;
00222     }
00223 
00224     aFilePaths.push_back( aTmpDir.filePath( aFileName ) );
00225     aFileSizes.push_back( aFile.size() );
00226     aBuffSize += aFileSizes.back();
00227 
00228     aFile.close();
00229   }
00230 
00231   if ( !aFilePaths.size() || !aBuffSize )
00232     return aStreamFile._retn(); 
00233     
00234   char* aBuffer = new char[aBuffSize + 1];
00235   if ( !aBuffer )
00236     return aStreamFile._retn();
00237 
00238   // Convert the file(s) to the byte stream, multiple files are simply
00239   // concatenated
00240   // TODO: imporve multi-script support if necessary...
00241   qint64 aCurrPos = 0;
00242   QStringList::const_iterator aFileIt  = aFilePaths.begin();
00243   QStringList::const_iterator aFileEnd = aFilePaths.end();
00244   QList<qint64>::const_iterator   aSIt = aFileSizes.begin();
00245   for ( ; aFileIt != aFileEnd; aFileIt++, aSIt++ ){
00246     QFile aFile( aTmpDir.filePath( *aFileIt ) );
00247     if ( !aFile.open( QIODevice::ReadOnly ) ){
00248       continue;
00249     }
00250 
00251     // Incorrect size of file
00252     // Do not remove the bad file to have some diagnostic means
00253     if ( aFile.read( aBuffer + aCurrPos, *aSIt ) != *aSIt ){
00254       aFile.close();      
00255       return aStreamFile._retn();
00256     }
00257 
00258     aCurrPos += (*aSIt); 
00259     aFile.remove();   
00260   }
00261 
00262   // Here we should end up with empty aTmpDir
00263   // TODO: Handle QDir::rmdir() error status somehow...
00264   aTmpDir.rmdir( aTmpPath );
00265 
00266   aBuffer[aBuffSize] = '\0';
00267   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
00268   aStreamFile = new Engines::TMPFile(aBuffSize + 1, aBuffSize + 1, anOctetBuf, 1); 
00269 
00270   return aStreamFile._retn();
00271 }
00272 
00276 char* SalomeApp_Engine_i::ComponentDataType()
00277 {
00278   return const_cast<char*>( myComponentName.c_str() );
00279 }
00280 
00284 CORBA::ORB_var SalomeApp_Engine_i::orb()
00285 {
00286   ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
00287   // TODO: using QApplication here looks ugly, think how to
00288   // obtain the ORB reference in a nicer way...
00289   static CORBA::ORB_var _orb = init( qApp->argc(), qApp->argv() );
00290   return _orb;
00291 }
00292 
00296 PortableServer::POA_var SalomeApp_Engine_i::poa()
00297 {
00298   static PortableServer::POA_var _poa;
00299   if ( CORBA::is_nil( _poa ) ){
00300     CORBA::Object_var obj = orb()->resolve_initial_references( "RootPOA" );
00301     _poa = PortableServer::POA::_narrow( obj );
00302   }
00303   return _poa;
00304 }
00305 
00309 SALOME_NamingService* SalomeApp_Engine_i::namingService()
00310 {
00311   static SALOME_NamingService _ns(orb());
00312   return &_ns;
00313 }
00314 
00324 CORBA::Object_ptr SalomeApp_Engine_i::engineForComponent( const char* theComponentName,
00325                                                    bool toCreate )
00326 {
00327   CORBA::Object_var anEngine;
00328   if ( !theComponentName || !strlen( theComponentName ) )
00329     return anEngine._retn();
00330 
00331   std::string aPath( "/SalomeAppEngine/" );
00332   aPath += theComponentName;
00333   anEngine = namingService()->Resolve( aPath.c_str() );
00334 
00335   // Activating a new instance of the servant
00336   if ( toCreate && CORBA::is_nil( anEngine ) ){
00337     try {
00338       SalomeApp_Engine_i* aServant    = new SalomeApp_Engine_i( theComponentName );
00339       PortableServer::ObjectId_var id = poa()->activate_object( aServant );
00340       anEngine = aServant->_this();
00341       aServant->_remove_ref();
00342       namingService()->Register( anEngine.in(), aPath.c_str() );
00343     }
00344     catch (CORBA::SystemException&) {
00345       INFOS("Caught CORBA::SystemException.");
00346     }
00347     catch (CORBA::Exception&) {
00348       INFOS("Caught CORBA::Exception.");
00349     }
00350     catch (...) {
00351       INFOS("Caught unknown exception.");
00352     }
00353   }
00354 
00355   return anEngine._retn();
00356 }
00357 
00364 std::string SalomeApp_Engine_i::EngineIORForComponent( const char* theComponentName,
00365                                                  bool toCreate )
00366 {
00367   std::string anIOR( "" );
00368   CORBA::Object_var anEngine = engineForComponent( theComponentName, toCreate );
00369   if ( !CORBA::is_nil( anEngine ) )
00370   {
00371     CORBA::String_var objStr = orb()->object_to_string( anEngine.in() );
00372     anIOR = std::string( objStr.in() );
00373   }
00374   return anIOR;
00375 }
00376 
00382 SalomeApp_Engine_i* SalomeApp_Engine_i::GetInstance( const char* theComponentName,
00383                                                bool toCreate )
00384 {
00385   SalomeApp_Engine_i* aServant = 0;
00386   CORBA::Object_var anEngine = engineForComponent( theComponentName, toCreate );
00387   if ( !CORBA::is_nil( anEngine ) )
00388   {
00389     PortableServer::Servant aServantBase = poa()->reference_to_servant( anEngine.in() );
00390     aServant = dynamic_cast<SalomeApp_Engine_i*>( aServantBase );
00391   } 
00392   MESSAGE("SalomeApp_Engine_i::GetInstance(): theComponentName = " <<
00393          theComponentName << ", aServant = " << aServant);
00394   return aServant;
00395 }
00396