Back to index

salome-gui  6.5.0
LightApp_Driver.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 #include "LightApp_Driver.h"
00024 
00025 #include <TCollection_AsciiString.hxx> 
00026 
00027 #include <OSD_Path.hxx>
00028 #include <OSD_File.hxx>
00029 #include <OSD_Directory.hxx>
00030 #include <OSD_Protection.hxx>
00031 #include <OSD_FileIterator.hxx>
00032 
00033 #include <QFileInfo>
00034 #include <QDir>
00035 
00036 #ifdef WIN32
00037 #include <time.h>
00038 #endif
00039 
00041 LightApp_Driver::LightApp_Driver()
00042 : myIsTemp( false )
00043 {
00044 }
00045  
00047 LightApp_Driver::~LightApp_Driver()
00048 {
00049 }
00050 
00054 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )
00055 {
00056   int aNbModules = 0;
00057   std::map<std::string, ListOfFiles>::const_iterator it;
00058   for (it = myMap.begin(); it != myMap.end(); ++it)
00059     aNbModules++;
00060 
00061   unsigned char** aBuffer = new unsigned char*[aNbModules]; 
00062   long*           aBufferSize = new long[aNbModules];
00063   char**          aModuleName = new char*[aNbModules];
00064 
00065   if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)
00066     return false;
00067 
00068   int aFileBufferSize = 4;  //4 bytes for a number of the modules that will be written to the stream;
00069   int i = 0;
00070   for (it = myMap.begin(); it != myMap.end(); ++it) {
00071     aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);
00072     aFileBufferSize += 4;                                //Add 4 bytes: a length of the module name
00073     aFileBufferSize += strlen(aModuleName[i])+1;
00074     std::string aName(aModuleName[i]);
00075     PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);
00076     aFileBufferSize += 8;                                //Add 8 bytes: a length of the buffer
00077     aFileBufferSize += aBufferSize[i];
00078     i++;
00079   }
00080   int n = i;
00081 
00082   unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
00083   if(aFileBuffer == NULL)
00084     return false;
00085 
00086   myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toLatin1().constData() ;
00087 
00088   int aCurrentPos = 0;
00089 
00090   //Initialize 4 bytes of the buffer by 0
00091   memset(aFileBuffer, 0, 4); 
00092   //Copy the number of modules that will be written to the stream
00093   memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));
00094   aCurrentPos += 4;
00095 
00096   int aBufferNameSize = 0;
00097   for (i = 0; i < n; i++) {
00098     aBufferNameSize = strlen(aModuleName[i])+1;
00099     //Initialize 4 bytes of the buffer by 0
00100     memset((aFileBuffer + aCurrentPos), 0, 4); 
00101     //Copy the length of the module name to the buffer
00102     memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int))); 
00103     aCurrentPos += 4;
00104     //Copy the module name to the buffer
00105     memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);
00106     aCurrentPos += aBufferNameSize;
00107 
00108     //Initialize 8 bytes of the buffer by 0
00109     memset((aFileBuffer + aCurrentPos), 0, 8);
00110     //Copy the length of the module buffer to the buffer
00111     memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
00112     aCurrentPos += 8;
00113     //Copy the module buffer to the buffer
00114     memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);
00115     aCurrentPos += aBufferSize[i];
00116   }
00117 
00118 #ifdef WIN32
00119   ofstream aFile(theFileName, ios::out | ios::binary);
00120 #else
00121   ofstream aFile(theFileName);
00122 #endif
00123   aFile.write((char*)aFileBuffer, aFileBufferSize); 
00124   aFile.close();    
00125 
00126   delete[] aBuffer;
00127   delete[] aBufferSize;
00128   delete[] aModuleName;
00129   delete[] aFileBuffer;
00130 
00131   return true;
00132 }
00133 
00137 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )
00138 {
00139 #ifdef WIN32
00140   ifstream aFile(theFileName, ios::binary);
00141 #else
00142   ifstream aFile(theFileName);
00143 #endif  
00144 
00145   myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toLatin1().constData() ;
00146 
00147   aFile.seekg(0, ios::end);
00148   int aFileBufferSize = aFile.tellg();
00149   unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
00150   aFile.seekg(0, ios::beg);
00151   aFile.read((char*)aFileBuffer, aFileBufferSize);
00152   aFile.close();
00153 
00154   int aNbModules = 0;
00155   //Copy the number of files in the stream
00156   memcpy(&aNbModules, aFileBuffer, sizeof(int));
00157   long aCurrentPos = 4;
00158   int aModuleNameSize;
00159 
00160   for (int i = 0; i < aNbModules; i++) {
00161     //Put a length of the module name to aModuleNameSize
00162     memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
00163     aCurrentPos += 4;
00164 
00165     char *aModuleName = new char[aModuleNameSize];
00166     //Put a module name to aModuleName
00167     memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize); 
00168     aCurrentPos += aModuleNameSize;
00169 
00170     //Put a length of the file buffer to aBufferSize
00171     long aBufferSize;
00172     memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); 
00173     aCurrentPos += 8;
00174     unsigned char *aBuffer = new unsigned char[aBufferSize];
00175  
00176     //Put a buffer for current module to aBuffer
00177     memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize); 
00178     aCurrentPos += aBufferSize;
00179 
00180     // Put buffer to aListOfFiles and set to myMap
00181     ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);
00182     SetListOfFiles(aModuleName, aListOfFiles);
00183 
00184     delete[] aModuleName;
00185     delete[] aBuffer;
00186   }
00187 
00188   delete[] aFileBuffer;
00189   
00190   return true;
00191 }
00192 
00196 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool  isMultiFile)
00197 {
00198   std::string anURLDir = GetDirFromPath(theURL);
00199   std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();
00200 
00201   return aTmpDir;
00202 }
00203 
00207 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )
00208 {
00209   ListOfFiles aListOfFiles;
00210 
00211   std::string aName(theModuleName);
00212   if (myMap.count(aName))
00213     aListOfFiles = myMap[aName];
00214 
00215     return aListOfFiles;
00216 }
00217 
00221 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )
00222 {
00223   std::string aName (theModuleName);
00224   myMap[aName] = theListOfFiles;
00225 }
00226 
00230 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,
00231                                         long& theBufferSize, bool theNamesOnly )
00232 {
00233   ListOfFiles aFiles = myMap[theModuleName];
00234   // aFiles must contain temporary directory name in its first item
00235   // and names of files (relatively the temporary directory) in the others
00236 
00237   int i, aLength = aFiles.size() - 1;
00238   if(aLength <= 0) {
00239     theBufferSize = 0;
00240     theBuffer = new unsigned char[theBufferSize];
00241     return;
00242   }
00243   //Get a temporary directory for saved a file
00244   TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));
00245 
00246   long aBufferSize = 0;
00247   long aCurrentPos;
00248   int aNbFiles = 0;
00249   int* aFileNameSize= new int[aLength];
00250   long* aFileSize= new long[aLength];
00251 
00252   //Determine the required size of the buffer
00253   TCollection_AsciiString aFileName;
00254   for (i = 0; i < aLength; i++) {
00255     char* aFName = const_cast<char*>(aFiles[i+1].c_str());
00256     aFileName = aFName;
00257     //Check if the file exists
00258     if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
00259       TCollection_AsciiString aFullPath = aTmpDir + aFileName;   
00260       OSD_Path anOSDPath(aFullPath);
00261       OSD_File anOSDFile(anOSDPath);
00262       if(!anOSDFile.Exists()) continue;
00263 #ifdef WIN32
00264       ifstream aFile(aFullPath.ToCString(), ios::binary);
00265 #else
00266       ifstream aFile(aFullPath.ToCString());
00267 #endif
00268       aFile.seekg(0, ios::end);
00269       aFileSize[i] = aFile.tellg();
00270       aBufferSize += aFileSize[i];              //Add a space to store the file
00271     }
00272     aFileNameSize[i] = strlen(aFName) + 1;
00273     aBufferSize += aFileNameSize[i];          //Add a space to store the file name
00274     aBufferSize += (theNamesOnly)?4:12;       //Add 4 bytes: a length of the file name,
00275                                               //    8 bytes: length of the file itself
00276     aNbFiles++;
00277   }
00278 
00279   aBufferSize += 4;      //4 bytes for a number of the files that will be written to the stream;
00280   theBuffer = new unsigned char[aBufferSize];  
00281   if(theBuffer == NULL) {
00282     theBufferSize = 0;
00283     theBuffer = 0;
00284     return;
00285   }
00286   //Initialize 4 bytes of the buffer by 0
00287   memset(theBuffer, 0, 4); 
00288   //Copy the number of files that will be written to the stream
00289   memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int))); 
00290 
00291   aCurrentPos = 4;
00292 
00293   for(i = 0; i < aLength; i++) {
00294     ifstream *aFile;
00295     if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
00296       TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));
00297       TCollection_AsciiString aFullPath = aTmpDir + aName;
00298       OSD_Path anOSDPath(aFullPath);
00299       OSD_File anOSDFile(anOSDPath);
00300       if(!anOSDFile.Exists()) continue;
00301 #ifdef WIN32
00302       aFile = new ifstream(aFullPath.ToCString(), ios::binary);
00303 #else
00304       aFile = new ifstream(aFullPath.ToCString());
00305 #endif
00306     }
00307     //Initialize 4 bytes of the buffer by 0
00308     memset((theBuffer + aCurrentPos), 0, 4); 
00309     //Copy the length of the file name to the buffer
00310     memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
00311     aCurrentPos += 4;
00312 
00313     //Copy the file name to the buffer
00314     char* aFName = const_cast<char*>(aFiles[i+1].c_str());
00315     memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);
00316     aCurrentPos += aFileNameSize[i];
00317     
00318     if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
00319       //Initialize 8 bytes of the buffer by 0
00320       memset((theBuffer + aCurrentPos), 0, 8); 
00321       //Copy the length of the file to the buffer
00322       memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
00323       aCurrentPos += 8;
00324       
00325       aFile->seekg(0, ios::beg);
00326       aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);
00327       aFile->close();
00328       delete(aFile);
00329       aCurrentPos += aFileSize[i];
00330     }
00331   }
00332   delete[] aFileNameSize;
00333   delete[] aFileSize;
00334 
00335   theBufferSize = aBufferSize;
00336 }
00337 
00341 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,
00342                                                                 const long theBufferSize, bool theNamesOnly )
00343 {
00344   if(theBufferSize == 0 || theBuffer == 0)
00345     return   ListOfFiles();
00346 
00347   // Create a temporary directory for the component's data files
00348   std::string aDir = GetTmpDir();
00349 
00350   // Remember that the files are in a temporary location that should be deleted
00351   // when a study is closed
00352   SetIsTemporary( true );
00353 
00354   //Get a temporary directory for saving a file
00355   TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));
00356 
00357   long aFileSize, aCurrentPos = 4;
00358   int i, aFileNameSize, aNbFiles = 0;
00359 
00360   //Copy the number of files in the stream
00361   memcpy(&aNbFiles, theBuffer, sizeof(int)); 
00362 
00363   const int n = aNbFiles + 1;
00364   ListOfFiles aFiles(n);
00365   aFiles[0] = aDir;
00366 
00367   for(i = 0; i < aNbFiles; i++) {
00368     //Put a length of the file name to aFileNameSize
00369     memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
00370     aCurrentPos += 4;
00371 
00372     char *aFileName = new char[aFileNameSize];
00373     //Put a file name to aFileName
00374     memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize); 
00375     aCurrentPos += aFileNameSize;
00376  
00377     //Put a length of the file to aFileSize
00378     if (!theNamesOnly) {
00379       memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
00380       aCurrentPos += 8;    
00381       
00382       TCollection_AsciiString aFullPath = aTmpDir + aFileName;
00383       
00384 #ifdef WIN32
00385   ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary);
00386 #else
00387   ofstream aFile(aFullPath.ToCString());
00388 #endif
00389 
00390       aFile.write((char *)(theBuffer+aCurrentPos), aFileSize); 
00391       aFile.close();  
00392       aCurrentPos += aFileSize;
00393     }
00394     std::string aStrFileName(aFileName);
00395     aFiles[i+1] = aStrFileName;
00396     delete[] aFileName;
00397   }
00398   return aFiles;
00399 }
00400 
00406 void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted)
00407 {
00408   int i, aLength = theFiles.size() - 1;
00409   if(aLength <= 0) {
00410     return;
00411   }
00412   //Get a temporary directory for saved a file
00413   TCollection_AsciiString aDirName(const_cast<char*>(theFiles[0].c_str()));
00414 
00415   for(i = 0; i < aLength; i++) {
00416     TCollection_AsciiString aFile(aDirName);
00417     aFile += const_cast<char*>(theFiles[i+1].c_str());
00418     OSD_Path anOSDPath(aFile);
00419     OSD_File anOSDFile(anOSDPath);
00420     if(!anOSDFile.Exists()) continue;
00421 
00422     anOSDFile.Remove();
00423   }
00424 
00425   if(IsDirDeleted) {
00426     OSD_Path aPath(aDirName);
00427     OSD_Directory aDir(aPath);
00428     // san -- Using a special code block below is essential - it ensures that
00429     // OSD_FileIterator instance is destroyed by the moment when
00430     // OSD_Directory::Remove() is called.
00431     // Otherwise, the directory remains locked (at least on Windows)
00432     // by the iterator and cannot be removed.
00433     {
00434       OSD_FileIterator anIterator(aPath, '*');
00435       if(!aDir.Exists() || anIterator.More())
00436         return;
00437     }
00438     aDir.Remove();
00439   }
00440 }
00441 
00446 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )
00447 {
00448   std::string aModuleName(theModuleName);
00449   ListOfFiles aFiles = myMap[aModuleName];
00450   // aFiles must contain temporary directory name in its first item
00451   // and names of files (relatively the temporary directory) in the others
00452   RemoveFiles( aFiles, IsDirDeleted );
00453 
00454 }
00455 
00459 void LightApp_Driver::ClearDriverContents()
00460 {
00461   std::map<std::string, ListOfFiles>::iterator it;
00462   for ( it = myMap.begin(); it != myMap.end(); ++it ) 
00463   {
00464     const char* aModuleName = const_cast<char*>(it->first.c_str());
00465     // If the driver contains temporary files - 
00466     // remove them along with the temporary directory
00467     RemoveTemporaryFiles( aModuleName, IsTemporary() );
00468   }
00469   myMap.clear();  
00470   // Reset the "temporary" flag
00471   SetIsTemporary( false );
00472 }
00473 
00477 std::string LightApp_Driver::GetTmpDir()
00478 {
00479   if ( myTmpDir.length() != 0 )
00480     return myTmpDir;
00481 
00482   //Find a temporary directory to store a file
00483   TCollection_AsciiString aTmpDir;
00484 
00485   char *Tmp_dir = getenv("SALOME_TMP_DIR");
00486   if ( !Tmp_dir )
00487     Tmp_dir = getenv ( "TEMP" );
00488   if ( !Tmp_dir )
00489     Tmp_dir = getenv ( "TMP" );
00490   if ( Tmp_dir ) 
00491   {
00492     aTmpDir = TCollection_AsciiString(Tmp_dir);
00493 #ifdef WIN32
00494     if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
00495 #else
00496     if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
00497 #endif      
00498   }
00499   else 
00500   {
00501 #ifdef WIN32
00502     aTmpDir = TCollection_AsciiString("C:\\");
00503 #else
00504     aTmpDir = TCollection_AsciiString("/tmp/");
00505 #endif
00506   }
00507 
00508   srand((unsigned int)time(NULL));
00509   int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
00510   TCollection_AsciiString aSubDir(aRND);
00511   if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");
00512 
00513   aTmpDir += aSubDir; //Get RND sub directory
00514 
00515 #ifdef WIN32
00516   if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
00517 #else
00518   if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
00519 #endif
00520 
00521   OSD_Path aPath(aTmpDir);
00522   OSD_Directory aDir(aPath);
00523 
00524   for(aRND = 0; aDir.Exists(); aRND++) {
00525     aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND));  //Build a unique directory name
00526     aPath = OSD_Path(aTmpDir);
00527     aDir = OSD_Directory(aPath);
00528   }
00529 
00530 #ifdef WIN32
00531   // Workaround for OSD_Protection bug on Windows
00532   OSD_Protection aProtection(OSD_RWXD, OSD_RWXD, OSD_RWXD, OSD_RWXD);
00533 #else
00534   OSD_Protection aProtection(OSD_RX, OSD_RWXD, OSD_RX, OSD_RX);
00535 #endif
00536   aDir.Build(aProtection);
00537 
00538   myTmpDir = aTmpDir.ToCString();
00539 
00540   return aTmpDir.ToCString();
00541 }
00542 
00546 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {
00547   if(thePath == "")
00548     return "";
00549   OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));
00550   TCollection_AsciiString aDirString(aPath.Trek());
00551   aDirString.ChangeAll('|','/');
00552   return aDirString.ToCString();
00553 }
00554