1 // Copyright (C) 2007-2012 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.
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 #include "LightApp_Driver.h"
25 #include <TCollection_AsciiString.hxx>
27 #include <OSD_Path.hxx>
28 #include <OSD_File.hxx>
29 #include <OSD_Directory.hxx>
30 #include <OSD_Protection.hxx>
31 #include <OSD_FileIterator.hxx>
41 LightApp_Driver::LightApp_Driver()
47 LightApp_Driver::~LightApp_Driver()
52 Save in file 'theFileName' datas from this driver
54 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )
57 std::map<std::string, ListOfFiles>::const_iterator it;
58 for (it = myMap.begin(); it != myMap.end(); ++it)
61 unsigned char** aBuffer = new unsigned char*[aNbModules];
62 long* aBufferSize = new long[aNbModules];
63 char** aModuleName = new char*[aNbModules];
65 if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)
68 int aFileBufferSize = 4; //4 bytes for a number of the modules that will be written to the stream;
70 for (it = myMap.begin(); it != myMap.end(); ++it) {
71 aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);
72 aFileBufferSize += 4; //Add 4 bytes: a length of the module name
73 aFileBufferSize += strlen(aModuleName[i])+1;
74 std::string aName(aModuleName[i]);
75 PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);
76 aFileBufferSize += 8; //Add 8 bytes: a length of the buffer
77 aFileBufferSize += aBufferSize[i];
82 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
83 if(aFileBuffer == NULL)
86 myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toLatin1().constData() ;
90 //Initialize 4 bytes of the buffer by 0
91 memset(aFileBuffer, 0, 4);
92 //Copy the number of modules that will be written to the stream
93 memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));
96 int aBufferNameSize = 0;
97 for (i = 0; i < n; i++) {
98 aBufferNameSize = strlen(aModuleName[i])+1;
99 //Initialize 4 bytes of the buffer by 0
100 memset((aFileBuffer + aCurrentPos), 0, 4);
101 //Copy the length of the module name to the buffer
102 memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int)));
104 //Copy the module name to the buffer
105 memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);
106 aCurrentPos += aBufferNameSize;
108 //Initialize 8 bytes of the buffer by 0
109 memset((aFileBuffer + aCurrentPos), 0, 8);
110 //Copy the length of the module buffer to the buffer
111 memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
113 //Copy the module buffer to the buffer
114 memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);
115 aCurrentPos += aBufferSize[i];
119 ofstream aFile(theFileName, ios::out | ios::binary);
121 ofstream aFile(theFileName);
123 aFile.write((char*)aFileBuffer, aFileBufferSize);
127 delete[] aBufferSize;
128 delete[] aModuleName;
129 delete[] aFileBuffer;
135 Filling current driver from file 'theFileName'
137 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )
140 ifstream aFile(theFileName, ios::binary);
142 ifstream aFile(theFileName);
145 myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toLatin1().constData() ;
147 aFile.seekg(0, ios::end);
148 int aFileBufferSize = aFile.tellg();
149 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
150 aFile.seekg(0, ios::beg);
151 aFile.read((char*)aFileBuffer, aFileBufferSize);
155 //Copy the number of files in the stream
156 memcpy(&aNbModules, aFileBuffer, sizeof(int));
157 long aCurrentPos = 4;
160 for (int i = 0; i < aNbModules; i++) {
161 //Put a length of the module name to aModuleNameSize
162 memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
165 char *aModuleName = new char[aModuleNameSize];
166 //Put a module name to aModuleName
167 memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize);
168 aCurrentPos += aModuleNameSize;
170 //Put a length of the file buffer to aBufferSize
172 memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
174 unsigned char *aBuffer = new unsigned char[aBufferSize];
176 //Put a buffer for current module to aBuffer
177 memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize);
178 aCurrentPos += aBufferSize;
180 // Put buffer to aListOfFiles and set to myMap
181 ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);
182 SetListOfFiles(aModuleName, aListOfFiles);
184 delete[] aModuleName;
188 delete[] aFileBuffer;
194 \return temp directory for path 'theURL'
196 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool isMultiFile)
198 std::string anURLDir = GetDirFromPath(theURL);
199 std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();
205 \return list of files for module with name 'theModuleName'
207 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )
209 ListOfFiles aListOfFiles;
211 std::string aName(theModuleName);
212 if (myMap.count(aName))
213 aListOfFiles = myMap[aName];
219 Sets list of files for module with name 'theModuleName'
221 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )
223 std::string aName (theModuleName);
224 myMap[aName] = theListOfFiles;
228 Converts files which was created from module <theModuleName> into a byte sequence unsigned char
230 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,
231 long& theBufferSize, bool theNamesOnly )
233 ListOfFiles aFiles = myMap[theModuleName];
234 // aFiles must contain temporary directory name in its first item
235 // and names of files (relatively the temporary directory) in the others
237 int i, aLength = aFiles.size() - 1;
240 theBuffer = new unsigned char[theBufferSize];
243 //Get a temporary directory for saved a file
244 TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));
246 long aBufferSize = 0;
249 int* aFileNameSize= new int[aLength];
250 long* aFileSize= new long[aLength];
252 //Determine the required size of the buffer
253 TCollection_AsciiString aFileName;
254 for (i = 0; i < aLength; i++) {
255 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
257 //Check if the file exists
258 if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
259 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
260 OSD_Path anOSDPath(aFullPath);
261 OSD_File anOSDFile(anOSDPath);
262 if(!anOSDFile.Exists()) continue;
264 ifstream aFile(aFullPath.ToCString(), ios::binary);
266 ifstream aFile(aFullPath.ToCString());
268 aFile.seekg(0, ios::end);
269 aFileSize[i] = aFile.tellg();
270 aBufferSize += aFileSize[i]; //Add a space to store the file
272 aFileNameSize[i] = strlen(aFName) + 1;
273 aBufferSize += aFileNameSize[i]; //Add a space to store the file name
274 aBufferSize += (theNamesOnly)?4:12; //Add 4 bytes: a length of the file name,
275 // 8 bytes: length of the file itself
279 aBufferSize += 4; //4 bytes for a number of the files that will be written to the stream;
280 theBuffer = new unsigned char[aBufferSize];
281 if(theBuffer == NULL) {
286 //Initialize 4 bytes of the buffer by 0
287 memset(theBuffer, 0, 4);
288 //Copy the number of files that will be written to the stream
289 memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int)));
293 for(i = 0; i < aLength; i++) {
295 if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
296 TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));
297 TCollection_AsciiString aFullPath = aTmpDir + aName;
298 OSD_Path anOSDPath(aFullPath);
299 OSD_File anOSDFile(anOSDPath);
300 if(!anOSDFile.Exists()) continue;
302 aFile = new ifstream(aFullPath.ToCString(), ios::binary);
304 aFile = new ifstream(aFullPath.ToCString());
307 //Initialize 4 bytes of the buffer by 0
308 memset((theBuffer + aCurrentPos), 0, 4);
309 //Copy the length of the file name to the buffer
310 memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int)));
313 //Copy the file name to the buffer
314 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
315 memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);
316 aCurrentPos += aFileNameSize[i];
318 if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
319 //Initialize 8 bytes of the buffer by 0
320 memset((theBuffer + aCurrentPos), 0, 8);
321 //Copy the length of the file to the buffer
322 memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
325 aFile->seekg(0, ios::beg);
326 aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);
329 aCurrentPos += aFileSize[i];
332 delete[] aFileNameSize;
335 theBufferSize = aBufferSize;
339 Converts a byte sequence <theBuffer> to files and return list of them
341 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,
342 const long theBufferSize, bool theNamesOnly )
344 if(theBufferSize == 0 || theBuffer == 0)
345 return ListOfFiles();
347 // Create a temporary directory for the component's data files
348 std::string aDir = GetTmpDir();
350 // Remember that the files are in a temporary location that should be deleted
351 // when a study is closed
352 SetIsTemporary( true );
354 //Get a temporary directory for saving a file
355 TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));
357 long aFileSize, aCurrentPos = 4;
358 int i, aFileNameSize, aNbFiles = 0;
360 //Copy the number of files in the stream
361 memcpy(&aNbFiles, theBuffer, sizeof(int));
363 const int n = aNbFiles + 1;
364 ListOfFiles aFiles(n);
367 for(i = 0; i < aNbFiles; i++) {
368 //Put a length of the file name to aFileNameSize
369 memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
372 char *aFileName = new char[aFileNameSize];
373 //Put a file name to aFileName
374 memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize);
375 aCurrentPos += aFileNameSize;
377 //Put a length of the file to aFileSize
379 memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
382 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
385 ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary);
387 ofstream aFile(aFullPath.ToCString());
390 aFile.write((char *)(theBuffer+aCurrentPos), aFileSize);
392 aCurrentPos += aFileSize;
394 std::string aStrFileName(aFileName);
395 aFiles[i+1] = aStrFileName;
402 Remove files. First item in <theFiles> is a directory with slash at the end.
403 Other items are names of files. If <IsDirDeleted> is true,
404 then the directory is also deleted.
406 void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted)
408 int i, aLength = theFiles.size() - 1;
412 //Get a temporary directory for saved a file
413 TCollection_AsciiString aDirName(const_cast<char*>(theFiles[0].c_str()));
415 for(i = 0; i < aLength; i++) {
416 TCollection_AsciiString aFile(aDirName);
417 aFile += const_cast<char*>(theFiles[i+1].c_str());
418 OSD_Path anOSDPath(aFile);
419 OSD_File anOSDFile(anOSDPath);
420 if(!anOSDFile.Exists()) continue;
426 OSD_Path aPath(aDirName);
427 OSD_Directory aDir(aPath);
428 // san -- Using a special code block below is essential - it ensures that
429 // OSD_FileIterator instance is destroyed by the moment when
430 // OSD_Directory::Remove() is called.
431 // Otherwise, the directory remains locked (at least on Windows)
432 // by the iterator and cannot be removed.
434 OSD_FileIterator anIterator(aPath, '*');
435 if(!aDir.Exists() || anIterator.More())
443 Removes files which was created from module theModuleName if
444 <IsDirDeleted> is true tmp directory is also deleted if it is empty
446 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )
448 std::string aModuleName(theModuleName);
449 ListOfFiles aFiles = myMap[aModuleName];
450 // aFiles must contain temporary directory name in its first item
451 // and names of files (relatively the temporary directory) in the others
452 RemoveFiles( aFiles, IsDirDeleted );
457 Clears map of list files
459 void LightApp_Driver::ClearDriverContents()
461 std::map<std::string, ListOfFiles>::iterator it;
462 for ( it = myMap.begin(); it != myMap.end(); ++it )
464 const char* aModuleName = const_cast<char*>(it->first.c_str());
465 // If the driver contains temporary files -
466 // remove them along with the temporary directory
467 RemoveTemporaryFiles( aModuleName, IsTemporary() );
470 // Reset the "temporary" flag
471 SetIsTemporary( false );
475 \return a temp directory to store created files like "/tmp/sub_dir/"
477 std::string LightApp_Driver::GetTmpDir()
479 if ( myTmpDir.length() != 0 )
482 //Find a temporary directory to store a file
483 TCollection_AsciiString aTmpDir;
485 char *Tmp_dir = getenv("SALOME_TMP_DIR");
487 Tmp_dir = getenv ( "TEMP" );
489 Tmp_dir = getenv ( "TMP" );
492 aTmpDir = TCollection_AsciiString(Tmp_dir);
494 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
496 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
502 aTmpDir = TCollection_AsciiString("C:\\");
504 aTmpDir = TCollection_AsciiString("/tmp/");
508 srand((unsigned int)time(NULL));
509 int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
510 TCollection_AsciiString aSubDir(aRND);
511 if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");
513 aTmpDir += aSubDir; //Get RND sub directory
516 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
518 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
521 OSD_Path aPath(aTmpDir);
522 OSD_Directory aDir(aPath);
524 for(aRND = 0; aDir.Exists(); aRND++) {
525 aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND)); //Build a unique directory name
526 aPath = OSD_Path(aTmpDir);
527 aDir = OSD_Directory(aPath);
531 // Workaround for OSD_Protection bug on Windows
532 OSD_Protection aProtection(OSD_RWXD, OSD_RWXD, OSD_RWXD, OSD_RWXD);
534 OSD_Protection aProtection(OSD_RX, OSD_RWXD, OSD_RX, OSD_RX);
536 aDir.Build(aProtection);
538 myTmpDir = aTmpDir.ToCString();
540 return aTmpDir.ToCString();
544 \return the dir by the path
546 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {
549 OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));
550 TCollection_AsciiString aDirString(aPath.Trek());
551 aDirString.ChangeAll('|','/');
552 return aDirString.ToCString();