]> SALOME platform Git repositories - modules/gui.git/blob - src/LightApp/LightApp_Driver.cxx
Salome HOME
Has functionality from SalomeApp without dependency from CORBA
[modules/gui.git] / src / LightApp / LightApp_Driver.cxx
1 #include "LightApp_Driver.h"\r
2 \r
3 #include <TCollection_AsciiString.hxx> \r
4 \r
5 #include <OSD_Path.hxx>\r
6 #include <OSD_File.hxx>\r
7 #include <OSD_Directory.hxx>\r
8 #include <OSD_Process.hxx>\r
9 #include <OSD_Directory.hxx>\r
10 #include <OSD_Protection.hxx>\r
11 #include <OSD_SingleProtection.hxx>\r
12 #include <OSD_FileIterator.hxx>\r
13 \r
14 #ifdef WIN32\r
15 #include <time.h>\r
16 #endif\r
17 \r
18 /*! Constructor.*/\r
19 LightApp_Driver::LightApp_Driver()\r
20 {\r
21 }\r
22  \r
23 /*! Destructor.*/\r
24 LightApp_Driver::~LightApp_Driver()\r
25 {\r
26 }\r
27 \r
28 using namespace std;\r
29 \r
30 //================================================================\r
31 // Function : SaveDatasInFile\r
32 /*! Purpose  : save in file 'theFileName' datas from this driver*/\r
33 //================================================================\r
34 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )\r
35 {\r
36   int aNbModules = 0;\r
37   std::map<std::string, ListOfFiles>::const_iterator it;\r
38   for (it = myMap.begin(); it != myMap.end(); ++it)\r
39     aNbModules++;\r
40 \r
41   unsigned char** aBuffer = new unsigned char*[aNbModules]; \r
42   long*           aBufferSize = new long[aNbModules];\r
43   char**          aModuleName = new char*[aNbModules];\r
44 \r
45   if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)\r
46     return false;\r
47 \r
48   int aFileBufferSize = 4;  //4 bytes for a number of the modules that will be written to the stream;\r
49   int i = 0;\r
50   for (it = myMap.begin(); it != myMap.end(); ++it) {\r
51     aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);\r
52     aFileBufferSize += 4;                                //Add 4 bytes: a length of the module name\r
53     aFileBufferSize += strlen(aModuleName[i])+1;\r
54     std::string aName(aModuleName[i]);\r
55     PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);\r
56     aFileBufferSize += 8;                                //Add 8 bytes: a length of the buffer\r
57     aFileBufferSize += aBufferSize[i];\r
58     // Remove the files and tmp directory, created by the component storage procedure\r
59     if (!isMultiFile)\r
60       RemoveTemporaryFiles(aModuleName[i], true);\r
61     i++;\r
62   }\r
63   int n = i;\r
64 \r
65   unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];\r
66   if(aFileBuffer == NULL)\r
67     return false;\r
68 \r
69   int aCurrentPos = 0;\r
70 \r
71   //Initialize 4 bytes of the buffer by 0\r
72   memset(aFileBuffer, 0, 4); \r
73   //Copy the number of modules that will be written to the stream\r
74   memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));\r
75   aCurrentPos += 4;\r
76 \r
77   int aBufferNameSize = 0;\r
78   for (i = 0; i < n; i++) {\r
79     aBufferNameSize = strlen(aModuleName[i])+1;\r
80     //Initialize 4 bytes of the buffer by 0\r
81     memset((aFileBuffer + aCurrentPos), 0, 4); \r
82     //Copy the length of the module name to the buffer\r
83     memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int))); \r
84     aCurrentPos += 4;\r
85     //Copy the module name to the buffer\r
86     memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);\r
87     aCurrentPos += aBufferNameSize;\r
88 \r
89     //Initialize 8 bytes of the buffer by 0\r
90     memset((aFileBuffer + aCurrentPos), 0, 8);\r
91     //Copy the length of the module buffer to the buffer\r
92     memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));\r
93     aCurrentPos += 8;\r
94     //Copy the module buffer to the buffer\r
95     memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);\r
96     aCurrentPos += aBufferSize[i];\r
97   }\r
98 \r
99   ofstream aFile(theFileName);\r
100   aFile.write((char*)aFileBuffer, aFileBufferSize); \r
101   aFile.close();    \r
102 \r
103   delete[] aBuffer;\r
104   delete[] aBufferSize;\r
105   delete[] aModuleName;\r
106   delete[] aFileBuffer;\r
107   return true;\r
108 }\r
109 \r
110 //=======================================================================\r
111 // name    : ReaDatasFromFile\r
112 /*! Purpose : filling current driver from file 'theFileName'*/\r
113 //=======================================================================\r
114 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )\r
115 {\r
116 #ifdef WNT\r
117   ifstream aFile(theFileName, ios::binary);\r
118 #else\r
119   ifstream aFile(theFileName);\r
120 #endif  \r
121 \r
122   aFile.seekg(0, ios::end);\r
123   int aFileBufferSize = aFile.tellg();\r
124   unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];\r
125   aFile.seekg(0, ios::beg);\r
126   aFile.read((char*)aFileBuffer, aFileBufferSize);\r
127   aFile.close();\r
128 \r
129   int aNbModules = 0;\r
130   //Copy the number of files in the stream\r
131   memcpy(&aNbModules, aFileBuffer, sizeof(int));\r
132   long aCurrentPos = 4;\r
133   int aModuleNameSize;\r
134 \r
135   for (int i = 0; i < aNbModules; i++) {\r
136     //Put a length of the module name to aModuleNameSize\r
137     memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); \r
138     aCurrentPos += 4;\r
139 \r
140     char *aModuleName = new char[aModuleNameSize];\r
141     //Put a module name to aModuleName\r
142     memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize); \r
143     aCurrentPos += aModuleNameSize;\r
144 \r
145     //Put a length of the file buffer to aBufferSize\r
146     long aBufferSize;\r
147     memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); \r
148     aCurrentPos += 8;\r
149     unsigned char *aBuffer = new unsigned char[aBufferSize];\r
150  \r
151     //Put a buffer for current module to aBuffer\r
152     memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize); \r
153     aCurrentPos += aBufferSize;\r
154 \r
155     // Put buffer to aListOfFiles and set to myMap\r
156     ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);\r
157     SetListOfFiles(aModuleName, aListOfFiles);\r
158 \r
159     delete[] aModuleName;\r
160     delete[] aBuffer;\r
161   }\r
162   delete[] aFileBuffer;\r
163   return true;\r
164 }\r
165 \r
166 //================================================================\r
167 // Function : GetTmpDir\r
168 /*! Purpose  : returns temp directory for path 'theURL'*/\r
169 //================================================================\r
170 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool  isMultiFile)\r
171 {\r
172   std::string anURLDir = GetDirFromPath(theURL);\r
173   std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();\r
174 \r
175   return aTmpDir;\r
176 }\r
177 \r
178 //================================================================\r
179 // Function : GetListOfFiles\r
180 /*! Purpose  : returns list of files for module with name 'theModuleName'*/\r
181 //================================================================\r
182 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )\r
183 {\r
184   ListOfFiles aListOfFiles;\r
185 \r
186   std::string aName(theModuleName);\r
187   if (myMap.count(aName))\r
188     aListOfFiles = myMap[aName];\r
189 \r
190     return aListOfFiles;\r
191 }\r
192 \r
193 //================================================================\r
194 // Function : SetListOfFiles\r
195 /*! Purpose  : sets list of files for module with name 'theModuleName'*/\r
196 //================================================================\r
197 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )\r
198 {\r
199   std::string aName (theModuleName);\r
200   myMap[aName] = theListOfFiles;\r
201 }\r
202 \r
203 //============================================================================\r
204 // function : PutFilesToStream\r
205 /*! Purpose  : converts files which was created from module <theModuleName> into a byte sequence unsigned char*/\r
206 //============================================================================\r
207 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,\r
208                                         long& theBufferSize, bool theNamesOnly )\r
209 {\r
210   ListOfFiles aFiles = myMap[theModuleName];\r
211   // aFiles must contain temporary directory name in its first item\r
212   // and names of files (relatively the temporary directory) in the others\r
213 \r
214   int i, aLength = aFiles.size() - 1;\r
215   if(aLength <= 0) {\r
216     theBufferSize = 0;\r
217     theBuffer = new unsigned char[theBufferSize];\r
218     return;\r
219   }\r
220   //Get a temporary directory for saved a file\r
221   TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));\r
222 \r
223   long aBufferSize = 0;\r
224   long aCurrentPos;\r
225   int aNbFiles = 0;\r
226   int* aFileNameSize= new int[aLength];\r
227   long* aFileSize= new long[aLength];\r
228 \r
229   //Determine the required size of the buffer\r
230   TCollection_AsciiString aFileName;\r
231   for (i = 0; i < aLength; i++) {\r
232     char* aFName = const_cast<char*>(aFiles[i+1].c_str());\r
233     aFileName = aFName;\r
234     //Check if the file exists\r
235     if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero\r
236       TCollection_AsciiString aFullPath = aTmpDir + aFileName;   \r
237       OSD_Path anOSDPath(aFullPath);\r
238       OSD_File anOSDFile(anOSDPath);\r
239       if(!anOSDFile.Exists()) continue;\r
240 #ifdef WNT\r
241       ifstream aFile(aFullPath.ToCString(), ios::binary);\r
242 #else\r
243       ifstream aFile(aFullPath.ToCString());\r
244 #endif\r
245       aFile.seekg(0, ios::end);\r
246       aFileSize[i] = aFile.tellg();\r
247       aBufferSize += aFileSize[i];              //Add a space to store the file\r
248     }\r
249     aFileNameSize[i] = strlen(aFName) + 1;\r
250     aBufferSize += aFileNameSize[i];          //Add a space to store the file name\r
251     aBufferSize += (theNamesOnly)?4:12;       //Add 4 bytes: a length of the file name,\r
252                                               //    8 bytes: length of the file itself\r
253     aNbFiles++;\r
254     delete[] aFName;\r
255   }\r
256 \r
257   aBufferSize += 4;      //4 bytes for a number of the files that will be written to the stream;\r
258   theBuffer = new unsigned char[aBufferSize];  \r
259   if(theBuffer == NULL) {\r
260     theBufferSize = 0;\r
261     theBuffer = 0;\r
262     return;\r
263   }\r
264   //Initialize 4 bytes of the buffer by 0\r
265   memset(theBuffer, 0, 4); \r
266   //Copy the number of files that will be written to the stream\r
267   memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int))); \r
268 \r
269   aCurrentPos = 4;\r
270 \r
271   for(i = 0; i < aLength; i++) {\r
272     ifstream *aFile;\r
273     if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true\r
274       TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));\r
275       TCollection_AsciiString aFullPath = aTmpDir + aName;\r
276       OSD_Path anOSDPath(aFullPath);\r
277       OSD_File anOSDFile(anOSDPath);\r
278       if(!anOSDFile.Exists()) continue;\r
279 #ifdef WNT\r
280       aFile = new ifstream(aFullPath.ToCString(), ios::binary);\r
281 #else\r
282       aFile = new ifstream(aFullPath.ToCString());\r
283 #endif\r
284     }\r
285     //Initialize 4 bytes of the buffer by 0\r
286     memset((theBuffer + aCurrentPos), 0, 4); \r
287     //Copy the length of the file name to the buffer\r
288     memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int))); \r
289     aCurrentPos += 4;\r
290 \r
291     //Copy the file name to the buffer\r
292     char* aFName = const_cast<char*>(aFiles[i+1].c_str());\r
293     memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);\r
294     aCurrentPos += aFileNameSize[i];\r
295     \r
296     if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly\r
297       //Initialize 8 bytes of the buffer by 0\r
298       memset((theBuffer + aCurrentPos), 0, 8); \r
299       //Copy the length of the file to the buffer\r
300       memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));\r
301       aCurrentPos += 8;\r
302       \r
303       aFile->seekg(0, ios::beg);\r
304       aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);\r
305       aFile->close();\r
306       delete(aFile);\r
307       aCurrentPos += aFileSize[i];\r
308     }\r
309   }\r
310   delete[] aFileNameSize;\r
311   delete[] aFileSize;\r
312 \r
313   theBufferSize = aBufferSize;\r
314 }\r
315 \r
316 //============================================================================\r
317 // function : PutStreamToFile\r
318 /*! Purpose  : converts a byte sequence <theBuffer> to files and return list of them*/\r
319 //============================================================================\r
320 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,\r
321                                                                 const long theBufferSize, bool theNamesOnly )\r
322 {\r
323   if(theBufferSize == 0 || theBuffer == 0)\r
324     return   ListOfFiles();\r
325 \r
326   // Create a temporary directory for the component's data files\r
327   std::string aDir = GetTmpDir();\r
328 \r
329   //Get a temporary directory for saving a file\r
330   TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));\r
331 \r
332   long aFileSize, aCurrentPos = 4;\r
333   int i, aFileNameSize, aNbFiles = 0;\r
334 \r
335   //Copy the number of files in the stream\r
336   memcpy(&aNbFiles, theBuffer, sizeof(int)); \r
337 \r
338   const int n = aNbFiles + 1;\r
339   ListOfFiles aFiles(n);\r
340   aFiles[0] = aDir;\r
341 \r
342   for(i = 0; i < aNbFiles; i++) {\r
343     //Put a length of the file name to aFileNameSize\r
344     memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); \r
345     aCurrentPos += 4;\r
346 \r
347     char *aFileName = new char[aFileNameSize];\r
348     //Put a file name to aFileName\r
349     memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize); \r
350     aCurrentPos += aFileNameSize;\r
351  \r
352     //Put a length of the file to aFileSize\r
353     if (!theNamesOnly) {\r
354       memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));\r
355       aCurrentPos += 8;    \r
356       \r
357       TCollection_AsciiString aFullPath = aTmpDir + aFileName;\r
358       ofstream aFile(aFullPath.ToCString());\r
359       aFile.write((char *)(theBuffer+aCurrentPos), aFileSize); \r
360       aFile.close();  \r
361       aCurrentPos += aFileSize;\r
362     }\r
363     std::string aStrFileName(aFileName);\r
364     aFiles[i+1] = aStrFileName;\r
365     delete[] aFileName;\r
366   }\r
367   return aFiles;\r
368 }\r
369 \r
370 //============================================================================\r
371 // function : RemoveTemporaryFiles\r
372 /*! Purpose  : removes files which was created from module theModuleName if <IsDirDeleted> is true tmp directory is also deleted if it is empty*/\r
373 //============================================================================\r
374 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )\r
375 {\r
376   std::string aModuleName(theModuleName);\r
377   ListOfFiles aFiles = myMap[aModuleName];\r
378   // aFiles must contain temporary directory name in its first item\r
379   // and names of files (relatively the temporary directory) in the others\r
380 \r
381   int i, aLength = aFiles.size() - 1;\r
382   if(aLength <= 0) {\r
383     return;\r
384   }\r
385   //Get a temporary directory for saved a file\r
386   TCollection_AsciiString aDirName(const_cast<char*>(aFiles[0].c_str()));\r
387 \r
388   for(i = 0; i < aLength; i++) {\r
389     TCollection_AsciiString aFile(aDirName);\r
390     aFile += const_cast<char*>(aFiles[i+1].c_str());\r
391     OSD_Path anOSDPath(aFile);\r
392     OSD_File anOSDFile(anOSDPath);\r
393     if(!anOSDFile.Exists()) continue;\r
394 \r
395     OSD_Protection aProtection = anOSDFile.Protection();\r
396     aProtection.SetUser(OSD_RW);\r
397     anOSDFile.SetProtection(aProtection);\r
398 \r
399     anOSDFile.Remove();\r
400   }\r
401 \r
402   if(IsDirDeleted) {\r
403     OSD_Path aPath(aDirName);\r
404     OSD_Directory aDir(aPath);\r
405     OSD_FileIterator anIterator(aPath, '*');\r
406 \r
407     if(aDir.Exists() && !anIterator.More()) aDir.Remove();\r
408   }\r
409 }\r
410 \r
411 //============================================================================\r
412 // function : ClearDriverContents\r
413 /*! Purpose  : clear map of list files*/ \r
414 //============================================================================ \r
415 void LightApp_Driver::ClearDriverContents()\r
416 {\r
417   myMap.clear();\r
418 }\r
419 \r
420 //============================================================================\r
421 // function : GetTempDir\r
422 /*! Purpose  : return a temp directory to store created files like "/tmp/sub_dir/" */\r
423 //============================================================================ \r
424 std::string LightApp_Driver::GetTmpDir()\r
425 {\r
426   //Find a temporary directory to store a file\r
427   TCollection_AsciiString aTmpDir;\r
428 \r
429   char *Tmp_dir = getenv("SALOME_TMP_DIR");\r
430   if(Tmp_dir != NULL) {\r
431     aTmpDir = TCollection_AsciiString(Tmp_dir);\r
432 #ifdef WIN32\r
433     if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';\r
434 #else\r
435     if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';\r
436 #endif      \r
437   }\r
438   else {\r
439 #ifdef WIN32\r
440     aTmpDir = TCollection_AsciiString("C:\\");\r
441 #else\r
442     aTmpDir = TCollection_AsciiString("/tmp/");\r
443 #endif\r
444   }\r
445 \r
446   srand((unsigned int)time(NULL));\r
447   int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory\r
448   TCollection_AsciiString aSubDir(aRND);\r
449   if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");\r
450 \r
451   aTmpDir += aSubDir; //Get RND sub directory\r
452 \r
453 #ifdef WIN32\r
454   if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';\r
455 #else\r
456   if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';\r
457 #endif\r
458 \r
459   OSD_Path aPath(aTmpDir);\r
460   OSD_Directory aDir(aPath);\r
461 \r
462   for(aRND = 0; aDir.Exists(); aRND++) {\r
463     aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND));  //Build a unique directory name\r
464     aPath = OSD_Path(aTmpDir);\r
465     aDir = OSD_Directory(aPath);\r
466   }\r
467 \r
468   OSD_Protection aProtection(OSD_RW, OSD_RWX, OSD_RX, OSD_RX);\r
469   aDir.Build(aProtection);\r
470 \r
471   return aTmpDir.ToCString();\r
472 }\r
473 \r
474 //============================================================================\r
475 // function : GetDirFromPath\r
476 /*! Purpose  : returns the dir by the path*/\r
477 //============================================================================\r
478 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {\r
479   if(thePath == "")\r
480     return "";\r
481   OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));\r
482   TCollection_AsciiString aDirString(aPath.Trek());\r
483   aDirString.ChangeAll('|','/');\r
484   return aDirString.ToCString();\r
485 }\r
486 \r