1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SalomeApp_Engine_i : implementation of SalomeApp_Engine.idl
24 // File : SalomeApp_Engine_i.cxx
25 // Author : Alexander SLADKOV
27 #include "SalomeApp_Engine_i.h"
28 #include "SalomeApp_Application.h"
30 #include <SALOME_NamingService.hxx>
31 #include <SALOMEDS_Tool.hxx>
32 #include <Utils_ORB_INIT.hxx>
33 #include <Utils_SINGLETON.hxx>
34 #include <Utils_SALOME_Exception.hxx>
35 #include <utilities.h>
37 #include <QApplication>
46 SalomeApp_Engine_i::SalomeApp_Engine_i( const char* theComponentName )
48 myComponentName = theComponentName;
49 MESSAGE("SalomeApp_Engine_i::SalomeApp_Engine_i(): myComponentName = " <<
50 myComponentName << ", this = " << this);
56 SalomeApp_Engine_i::~SalomeApp_Engine_i()
58 MESSAGE("SalomeApp_Engine_i::~SalomeApp_Engine_i(): myComponentName = " <<
59 myComponentName << ", this = " << this);
62 SALOMEDS::TMPFile* SalomeApp_Engine_i::Save (SALOMEDS::SComponent_ptr theComponent,
66 SALOMEDS::TMPFile_var aStreamFile = new SALOMEDS::TMPFile;
68 if (CORBA::is_nil(theComponent))
69 return aStreamFile._retn();
71 // Get a temporary directory to store a file
72 //std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
74 std::string componentName (theComponent->ComponentDataType());
76 // Error somewhere outside - Save() called with
77 // wrong SComponent instance
78 if ( myComponentName != componentName )
79 return aStreamFile._retn();
81 // listOfFiles must contain temporary directory name in its first item
82 // and names of files (relatively the temporary directory) in the others
83 const int n = myListOfFiles.size() - 1;
85 if (n > 0) { // there are some files, containing persistent data of the component
86 std::string aTmpDir = myListOfFiles[0];
88 // Create a list to store names of created files
91 for (int i = 0; i < n; i++)
92 aSeq.push_back(CORBA::string_dup(myListOfFiles[i + 1].c_str()));
94 // Convert a file to the byte stream
95 aStreamFile = SALOMEDS_Tool::PutFilesToStream(aTmpDir.c_str(), aSeq, isMultiFile);
97 // Remove the files and tmp directory, created by the component storage procedure
98 if (!isMultiFile) SALOMEDS_Tool::RemoveTemporaryFiles(aTmpDir.c_str(), aSeq, true);
101 return aStreamFile._retn();
104 CORBA::Boolean SalomeApp_Engine_i::Load (SALOMEDS::SComponent_ptr theComponent,
105 const SALOMEDS::TMPFile& theFile,
109 std::cout << "SalomeApp_Engine_i::Load() isMultiFile = " << isMultiFile << std::endl;
110 if (CORBA::is_nil(theComponent))
113 // Error somewhere outside - Load() called with
114 // wrong SComponent instance
115 std::string componentName (theComponent->ComponentDataType());
116 if ( myComponentName != componentName )
119 // Create a temporary directory for the component's data files
120 std::string aTmpDir = isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir();
122 // Convert the byte stream theStream to a files and place them in the tmp directory.
123 // The files and temporary directory must be deleted by the component loading procedure.
125 SALOMEDS_Tool::PutStreamToFiles(theFile, aTmpDir.c_str(), isMultiFile);
127 // Store list of file names to be used by the component loading procedure
128 const int n = aSeq.size() + 1;
129 ListOfFiles listOfFiles (n);
130 listOfFiles[0] = aTmpDir;
131 for (int i = 1; i < n; i++)
132 listOfFiles[i] = std::string(aSeq[i - 1]);
134 SetListOfFiles(listOfFiles);
139 SalomeApp_Engine_i::ListOfFiles SalomeApp_Engine_i::GetListOfFiles()
141 return myListOfFiles;
144 void SalomeApp_Engine_i::SetListOfFiles (const ListOfFiles& theListOfFiles)
146 myListOfFiles = theListOfFiles;
150 * DumpPython implementation for light modules
152 Engines::TMPFile* SalomeApp_Engine_i::DumpPython(CORBA::Boolean isPublished,
153 CORBA::Boolean isMultiFile,
154 CORBA::Boolean& isValidScript)
156 MESSAGE("SalomeApp_Engine_i::DumpPython(): myComponentName = "<<
157 myComponentName << ", this = " << this);
159 // Temporary solution: returning a non-empty sequence
160 // even if there's nothing to dump, to avoid crashes in SALOMEDS
161 // TODO: Improve SALOMEDSImpl_Study::DumpStudy() by skipping the components
162 // with isValidScript == false, and initialize isValidScript by false below.
163 Engines::TMPFile_var aStreamFile = new Engines::TMPFile(1);
164 aStreamFile->length( 1 );
165 aStreamFile[0] = '\0';
166 isValidScript = true;
168 // listOfFiles must contain temporary directory name in its first item
169 // and names of files (relatively the temporary directory) in the others
170 if ( myListOfFiles.size() < 2 )
171 return aStreamFile._retn();
173 // there are some files, containing persistent data of the component
174 QString aTmpPath( myListOfFiles.front().c_str() );
175 QDir aTmpDir( aTmpPath );
176 if ( !aTmpDir.exists() )
177 return aStreamFile._retn();
179 // Calculate file sizes
180 QStringList aFilePaths;
181 QList<qint64> aFileSizes;
182 qint64 aBuffSize = 0;
183 ListOfFiles::const_iterator aFIt = myListOfFiles.begin();
184 ListOfFiles::const_iterator aFEnd = myListOfFiles.end();
186 for (; aFIt != aFEnd; aFIt++){
187 QString aFileName( (*aFIt).c_str() );
188 if ( !aTmpDir.exists( aFileName ) ){
192 QFile aFile( aTmpDir.filePath( aFileName ) );
193 if ( !aFile.open( QIODevice::ReadOnly ) ){
197 aFilePaths.push_back( aTmpDir.filePath( aFileName ) );
198 aFileSizes.push_back( aFile.size() );
199 aBuffSize += aFileSizes.back();
204 if ( !aFilePaths.size() || !aBuffSize )
205 return aStreamFile._retn();
207 char* aBuffer = new char[aBuffSize + 1];
209 return aStreamFile._retn();
211 // Convert the file(s) to the byte stream, multiple files are simply
213 // TODO: imporve multi-script support if necessary...
215 QStringList::const_iterator aFileIt = aFilePaths.begin();
216 QStringList::const_iterator aFileEnd = aFilePaths.end();
217 QList<qint64>::const_iterator aSIt = aFileSizes.begin();
218 for ( ; aFileIt != aFileEnd; aFileIt++, aSIt++ ){
219 QFile aFile( aTmpDir.filePath( *aFileIt ) );
220 if ( !aFile.open( QIODevice::ReadOnly ) ){
224 // Incorrect size of file
225 // Do not remove the bad file to have some diagnostic means
226 if ( aFile.read( aBuffer + aCurrPos, *aSIt ) != *aSIt ){
228 return aStreamFile._retn();
235 // Here we should end up with empty aTmpDir
236 // TODO: Handle QDir::rmdir() error status somehow...
237 aTmpDir.rmdir( aTmpPath );
239 aBuffer[aBuffSize] = '\0';
240 CORBA::Octet* anOctetBuf = (CORBA::Octet*)aBuffer;
241 aStreamFile = new Engines::TMPFile(aBuffSize + 1, aBuffSize + 1, anOctetBuf, 1);
243 return aStreamFile._retn();
247 \return Component data type string for this instance of the engine
249 char* SalomeApp_Engine_i::ComponentDataType()
251 return const_cast<char*>( myComponentName.c_str() );
255 \return Component version
257 char* SalomeApp_Engine_i::getVersion()
259 SalomeApp_Application::ModuleShortInfoList versions = SalomeApp_Application::getVersionInfo();
261 SalomeApp_Application::ModuleShortInfo version_info;
262 foreach ( version_info, versions ) {
263 if ( SalomeApp_Application::moduleName( version_info.name ) == myComponentName.c_str() ) {
264 version = version_info.version;
269 return CORBA::string_dup( version.toLatin1().constData() );
275 CORBA::ORB_var SalomeApp_Engine_i::orb()
277 static CORBA::ORB_var _orb;
279 if ( CORBA::is_nil( _orb ) ) {
280 Qtx::CmdLineArgs args;
281 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
282 _orb = init( args.argc(), args.argv() );
291 PortableServer::POA_var SalomeApp_Engine_i::poa()
293 static PortableServer::POA_var _poa;
294 if ( CORBA::is_nil( _poa ) ){
295 CORBA::Object_var obj = orb()->resolve_initial_references( "RootPOA" );
296 _poa = PortableServer::POA::_narrow( obj );
304 SALOME_NamingService* SalomeApp_Engine_i::namingService()
306 static SALOME_NamingService _ns(orb());
311 Internal method, creates a CORBA engine for a light SALOME module
312 with the given "component data type" string,
313 activates it and registers in SALOME naming service with
314 /SalomeAppEngine/comp_data_type path. If the engine is already in the
315 naming service, simply returns and object reference to it.
316 \param theComponentName - synthetic "component data type" used to identify a given light module
317 \return Object reference to the CORBA engine
319 CORBA::Object_ptr SalomeApp_Engine_i::EngineForComponent( const char* theComponentName,
322 CORBA::Object_var anEngine;
323 if ( !theComponentName || !strlen( theComponentName ) )
324 return anEngine._retn();
326 if ( SalomeApp_Application::moduleTitle( theComponentName ).isEmpty() )
327 return anEngine._retn();
329 std::string aPath( "/SalomeAppEngine/" );
330 aPath += theComponentName;
331 anEngine = namingService()->Resolve( aPath.c_str() );
333 // Activating a new instance of the servant
334 if ( toCreate && CORBA::is_nil( anEngine ) ){
336 SalomeApp_Engine_i* aServant = new SalomeApp_Engine_i( theComponentName );
337 PortableServer::ObjectId_var id = poa()->activate_object( aServant );
338 anEngine = aServant->_this();
339 aServant->_remove_ref();
340 namingService()->Register( anEngine.in(), aPath.c_str() );
342 catch (CORBA::SystemException&) {
343 INFOS("Caught CORBA::SystemException.");
345 catch (CORBA::Exception&) {
346 INFOS("Caught CORBA::Exception.");
349 INFOS("Caught unknown exception.");
353 return anEngine._retn();
357 \param theComponentName - synthetic "component data type" used to identify a given light module
358 \return IOR string for the CORBA engine for a light SALOME module
359 with the given "component data type" string
360 \sa GetInstance( const char* theComponentName )
362 std::string SalomeApp_Engine_i::EngineIORForComponent( const char* theComponentName,
365 std::string anIOR( "" );
366 CORBA::Object_var anEngine = EngineForComponent( theComponentName, toCreate );
367 if ( !CORBA::is_nil( anEngine ) )
369 CORBA::String_var objStr = orb()->object_to_string( anEngine.in() );
370 anIOR = std::string( objStr.in() );
376 \param theComponentName - synthetic "component data type" used to identify a given light module
377 \return A pointer to corresponding C++ engine instance, null means some internal problems.
378 \sa EngineIORForComponent( const char* theComponentName )
380 SalomeApp_Engine_i* SalomeApp_Engine_i::GetInstance( const char* theComponentName,
383 SalomeApp_Engine_i* aServant = 0;
384 CORBA::Object_var anEngine = EngineForComponent( theComponentName, toCreate );
385 if ( !CORBA::is_nil( anEngine ) )
387 PortableServer::Servant aServantBase = poa()->reference_to_servant( anEngine.in() );
388 aServant = dynamic_cast<SalomeApp_Engine_i*>( aServantBase );
390 MESSAGE("SalomeApp_Engine_i::GetInstance(): theComponentName = " <<
391 theComponentName << ", aServant = " << aServant);