Salome HOME
8d3b448bfc4ec5072dfbaa910d899032d8730ab6
[modules/kernel.git] / src / TOOLSDS / SALOMEDS_Tool.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File      : SALOMEDS_Tool.cxx
24 //  Created   : Mon Oct 21 16:24:34 2002
25 //  Author    : Sergey RUIN
26 //  Project   : SALOME
27 //  Module    : SALOMEDS
28 //
29 #include "SALOMEDS_Tool.hxx"
30
31 #include "utilities.h"
32 #include "Basics_DirUtils.hxx"
33 #include "Basics_Utils.hxx"
34
35 #ifndef WIN32
36 #include <sys/time.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <pwd.h> 
40 #include <unistd.h>
41 #else
42 #include <time.h>
43 #include <lmcons.h>
44 #endif
45
46 #include <iostream> 
47 #include <fstream>
48
49 #include <SALOMEconfig.h>
50 #include CORBA_SERVER_HEADER(SALOMEDS_Attributes)
51
52 bool Exists(const std::string thePath) 
53 {
54         return Kernel_Utils::IsExists(thePath);
55 }
56
57
58 //============================================================================
59 // function : GetTempDir
60 // purpose  : Return a temp directory to store created files like "/tmp/sub_dir/" 
61 //============================================================================ 
62 std::string SALOMEDS_Tool::GetTmpDir()
63 {
64   return Kernel_Utils::GetTmpDirByEnv("SALOME_TMP_DIR");
65   //Find a temporary directory to store a file
66
67   /*string aTmpDir = "";
68
69   char *Tmp_dir = getenv("SALOME_TMP_DIR");
70   if(Tmp_dir != NULL) {
71     aTmpDir = string(Tmp_dir);
72 #ifdef WIN32
73     if(aTmpDir[aTmpDir.size()-1] != '\\') aTmpDir+='\\';
74 #else
75     if(aTmpDir[aTmpDir.size()-1] != '/') aTmpDir+='/';
76 #endif      
77   }
78   else {
79 #ifdef WIN32
80     aTmpDir = string("C:\\");
81 #else
82     aTmpDir = string("/tmp/");
83 #endif
84   }
85
86   srand((unsigned int)time(NULL));
87   int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
88   char buffer[127];
89   sprintf(buffer, "%d", aRND);
90   string aSubDir(buffer);
91   if(aSubDir.size() <= 1) aSubDir = string("123409876");
92
93   aTmpDir += aSubDir; //Get RND sub directory
94
95   string aDir = aTmpDir;
96
97   if(Exists(aDir)) {
98     for(aRND = 0; Exists(aDir); aRND++) {
99       sprintf(buffer, "%d", aRND);
100       aDir = aTmpDir+buffer;  //Build a unique directory name
101     }
102   }
103
104 #ifdef WIN32
105   if(aDir[aDir.size()-1] != '\\') aDir+='\\';
106 #else
107   if(aDir[aTmpDir.size()-1] != '/') aDir+='/';
108 #endif
109
110
111 #ifdef WIN32
112   CreateDirectory(aDir.c_str(), NULL);
113 #else
114   mkdir(aDir.c_str(), 0x1ff); 
115 #endif
116
117   return aDir;*/
118 }
119
120 //============================================================================
121 // function : RemoveTemporaryFiles
122 // purpose  : Removes files listed in theFileList
123 //============================================================================
124 void SALOMEDS_Tool::RemoveTemporaryFiles(const std::string& theDirectory, 
125                                          const ListOfFiles& theFiles,
126                                          const bool IsDirDeleted)
127 {
128   std::string aDirName = theDirectory;
129
130   size_t i, aLength = theFiles.size();
131   for(i=1; i<=aLength; i++) {
132     std::string aFile(aDirName);
133     aFile += theFiles[i-1];
134     if(!Exists(aFile)) continue;
135
136 #ifdef WIN32
137 #if defined(UNICODE)
138         std::wstring aFileToDelete = Kernel_Utils::utf8_decode_s(aFile);
139 #else
140         std::string aFileToDelete = aFile;
141 #endif
142     DeleteFile(aFileToDelete.c_str());
143 #else 
144     unlink(aFile.c_str());
145 #endif
146   }
147
148   if(IsDirDeleted) {
149     if(Exists(aDirName)) {
150 #ifdef WIN32
151 #if defined(UNICODE)
152                 std::wstring aDirToDelete = Kernel_Utils::utf8_decode_s(aDirName);
153 #else
154                 std::string aDirToDelete = aDirName;
155 #endif
156       RemoveDirectory(aDirToDelete.c_str());
157 #else
158       rmdir(aDirName.c_str());
159 #endif
160     }
161   }
162
163 }
164
165 //============================================================================
166 // function : PutFilesToStream
167 // purpose  : converts the files from a list 'theFiles' to the stream
168 //============================================================================
169 namespace
170 {
171   SALOMEDS::TMPFile* 
172   PutFilesToStream(const std::string& theFromDirectory,
173                    const std::vector<std::string>& theFiles,
174                    const std::vector<std::string>& theFileNames,
175                    const int theNamesOnly)
176   {
177     int i, aLength = (int)theFiles.size(); //!< TODO: conversion from size_t to int
178     if(aLength == 0)
179       return (new SALOMEDS::TMPFile);
180     
181     //Get a temporary directory for saved a file
182     std::string aTmpDir = theFromDirectory;
183     
184     long aBufferSize = 0;
185     long aCurrentPos;
186     
187     int aNbFiles = 0;
188     int* aFileNameSize= new int[aLength];
189     long* aFileSize= new long[aLength];
190     
191     //Determine the required size of the buffer
192     
193     for(i=0; i<aLength; i++) {
194       
195       //Check if the file exists
196       
197       if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
198         std::string aFullPath = aTmpDir + theFiles[i];
199         if(!Exists(aFullPath)) continue;
200 #ifdef WIN32
201 #ifdef UNICODE
202                 std::ifstream aFile(Kernel_Utils::utf8_decode_s(aFullPath).c_str(), std::ios::binary);
203 #else
204         std::ifstream aFile(aFullPath.c_str(), std::ios::binary);
205 #endif
206 #else
207         std::ifstream aFile(aFullPath.c_str());
208 #endif
209         aFile.seekg(0, std::ios::end);
210         aFileSize[i] = (long)aFile.tellg(); //!< TODO: conversion from std::streamoff to long
211         aBufferSize += aFileSize[i];              //Add a space to store the file
212       }
213       aFileNameSize[i] = (int)theFileNames[i].length()+1; //!< TODO: conversion from size_t to int
214       aBufferSize += aFileNameSize[i];          //Add a space to store the file name
215       aBufferSize += (theNamesOnly)?4:12;       //Add 4 bytes: a length of the file name,
216       //    8 bytes: length of the file itself
217       aNbFiles++;
218     } 
219     
220     if ( aNbFiles == 0 ) return (new SALOMEDS::TMPFile);
221     aBufferSize += 4;      //4 bytes for a number of the files that will be written to the stream;
222         unsigned char* aBuffer = new unsigned char[aBufferSize];
223
224     if(aBuffer == NULL)
225       return (new SALOMEDS::TMPFile);
226     
227     //Initialize 4 bytes of the buffer by 0
228     memset(aBuffer, 0, 4); 
229     //Copy the number of files that will be written to the stream
230     memcpy(aBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int))); 
231     
232     
233     aCurrentPos = 4;
234     
235     for(i=0; i<aLength; i++) {
236           std::ifstream *aFile;
237       if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
238         std::string aFullPath = aTmpDir + theFiles[i];
239         if(!Exists(aFullPath)) continue;
240 #ifdef WIN32
241 #ifdef UNICODE
242                 aFile = new std::ifstream (Kernel_Utils::utf8_decode_s(aFullPath).c_str(), std::ios::binary);
243 #else
244         aFile = new std::ifstream(aFullPath.c_str(), std::ios::binary);
245 #endif
246 #else
247         aFile = new std::ifstream(aFullPath.c_str());
248 #endif  
249       }
250       //Initialize 4 bytes of the buffer by 0
251       memset((aBuffer + aCurrentPos), 0, 4); 
252       //Copy the length of the file name to the buffer
253       memcpy((aBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
254       aCurrentPos += 4;
255       
256       //Copy the file name to the buffer
257       memcpy((aBuffer + aCurrentPos), theFileNames[i].c_str(), aFileNameSize[i]);
258       aCurrentPos += aFileNameSize[i];
259       
260       if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
261         //Initialize 8 bytes of the buffer by 0
262         memset((aBuffer + aCurrentPos), 0, 8); 
263         //Copy the length of the file to the buffer
264         memcpy((aBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
265         aCurrentPos += 8;
266         
267         aFile->seekg(0, std::ios::beg);
268                 aFile->read((char *)(aBuffer + aCurrentPos), aFileSize[i]);
269         aFile->close();
270         delete(aFile);
271         aCurrentPos += aFileSize[i];
272       }
273     }
274     
275     delete[] aFileNameSize;
276     delete[] aFileSize;
277     
278     
279     CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
280     
281     return (new SALOMEDS::TMPFile(aBufferSize, aBufferSize, anOctetBuf, 1));
282   }
283   
284 }
285
286
287 SALOMEDS::TMPFile* 
288 SALOMEDS_Tool::PutFilesToStream(const std::string& theFromDirectory,
289                                 const ListOfFiles& theFiles,
290                                 const int theNamesOnly)
291 {
292   ListOfFiles aFileNames(theFiles);
293   return ::PutFilesToStream(theFromDirectory,theFiles,aFileNames,theNamesOnly);
294 }
295
296
297 SALOMEDS::TMPFile* 
298 SALOMEDS_Tool::PutFilesToStream(const ListOfFiles& theFiles,
299                                 const ListOfFiles& theFileNames)
300 {
301   return ::PutFilesToStream("",theFiles,theFileNames,0);
302 }
303
304 //============================================================================
305 // function : PutStreamToFile
306 // purpose  : converts the stream "theStream" to the files
307 //============================================================================
308 SALOMEDS_Tool::ListOfFiles
309 SALOMEDS_Tool::PutStreamToFiles(const SALOMEDS::TMPFile& theStream,
310                                 const std::string& theToDirectory,
311                                 const int theNamesOnly)
312 {
313   ListOfFiles aFiles;
314
315   if(theStream.length() == 0)
316     return aFiles;
317
318   //Get a temporary directory for saving a file
319   std::string aTmpDir = theToDirectory;
320   unsigned char *aBuffer = (unsigned char*)theStream.NP_data();
321
322   if(aBuffer == NULL)
323     return aFiles;
324
325   long aFileSize, aCurrentPos = 4;
326   int i, aFileNameSize, aNbFiles = 0;
327
328   //Copy the number of files in the stream
329   memcpy(&aNbFiles, aBuffer, sizeof(int)); 
330
331   aFiles.reserve(aNbFiles);
332
333   for(i=0; i<aNbFiles; i++) {
334
335     //Put a length of the file name to aFileNameSize
336     memcpy(&aFileNameSize, (aBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
337     aCurrentPos += 4;
338
339     char *aFileName = new char[aFileNameSize];
340     //Put a file name to aFileName
341     memcpy(aFileName, (aBuffer + aCurrentPos), aFileNameSize); 
342 #ifdef WIN32
343     for (int j = 0; j < strlen(aFileName); j++)
344     {
345       if (aFileName[j] == ':')
346         aFileName[j] = '_';
347     }
348 #endif
349     aCurrentPos += aFileNameSize;
350  
351     //Put a length of the file to aFileSize
352     if (!theNamesOnly) {
353       memcpy(&aFileSize, (aBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
354       aCurrentPos += 8;    
355       
356       std::string aFullPath = aTmpDir + aFileName;
357 #ifdef WIN32
358 #ifdef UNICODE
359           std::ofstream aFile(Kernel_Utils::utf8_decode_s(aFullPath).c_str(), std::ios::binary);
360 #else
361       std::ofstream aFile(aFullPath.c_str(), std::ios::binary);
362 #endif
363 #else
364       std::ofstream aFile(aFullPath.c_str());
365 #endif
366           aFile.write((char *)(aBuffer + aCurrentPos), aFileSize);
367       aFile.close();  
368       aCurrentPos += aFileSize;
369     }
370     aFiles.push_back(aFileName);
371     delete[] aFileName;
372   }
373
374   return aFiles;
375 }
376
377 //============================================================================
378 // function : GetNameFromPath
379 // purpose  : Returns the name by the path
380 //============================================================================
381 std::string SALOMEDS_Tool::GetNameFromPath(const std::string& thePath) {
382   if (thePath.empty()) return "";
383   std::string aPath = thePath;
384   bool isFound = false;
385   size_t pos = aPath.rfind('/');
386   if(pos != std::string::npos) {
387     aPath = aPath.substr(pos+1, aPath.size());
388     isFound = true;
389   }    
390   if(!isFound) {
391     pos = aPath.rfind('\\'); 
392     if(pos != std::string::npos) {
393       aPath = aPath.substr(pos+1, aPath.size()); 
394       isFound = true;
395     }  
396   }  
397   if(!isFound) {  
398     pos = aPath.rfind('|');
399     if(pos != std::string::npos) aPath = aPath.substr(pos+1, aPath.size()); 
400   }
401
402   pos = aPath.rfind('.'); 
403   if(pos != std::string::npos)  aPath = aPath.substr(0, pos); //Remove extension
404     
405   return aPath;
406 }
407
408 //============================================================================
409 // function : GetDirFromPath
410 // purpose  : Returns the dir by the path
411 //============================================================================
412 std::string SALOMEDS_Tool::GetDirFromPath(const std::string& thePath) {
413   if (thePath.empty()) return "";
414
415   size_t pos = thePath.rfind('/');
416   std::string path;
417   if(pos != std::string::npos) {
418     path = thePath.substr(0, pos+1);
419   }
420   if(path.empty()) {
421     pos = thePath.rfind('\\');
422     if(pos != std::string::npos) path = thePath.substr(0, pos+1); 
423   }
424   if(path.empty()) {
425     pos = thePath.rfind('|');
426     if(pos != std::string::npos) path = thePath.substr(0, pos+1); 
427   }
428   if(path.empty()) {
429     path = thePath+"/";
430   }
431   
432 #ifdef WIN32  //Check if the only disk letter is given as path
433   if(path.size() == 2 && path[1] == ':') path +='\\';
434 #endif
435
436   for(size_t i = 0, len = path.size(); i<len; i++) 
437     if(path[i] == '|') path[i] = '/';
438   return path;
439 }
440
441 //=======================================================================
442 // name    : GetFlag
443 // Purpose : Retrieve specified flaf from "AttributeFlags" attribute
444 //=======================================================================
445 bool SALOMEDS_Tool::GetFlag( const int             theFlag,
446                              SALOMEDS::Study_var   /*theStudy*/,
447                              SALOMEDS::SObject_var theObj )
448 {
449   SALOMEDS::GenericAttribute_var anAttr;
450   if ( !theObj->_is_nil() && theObj->FindAttribute( anAttr, "AttributeFlags" ) )
451   {
452     SALOMEDS::AttributeFlags_var aFlags = SALOMEDS::AttributeFlags::_narrow( anAttr );
453     return aFlags->Get( theFlag );
454   }
455
456   return false;
457 }
458
459 //=======================================================================
460 // name    : SetFlag
461 // Purpose : Set/Unset specified flaf from "AttributeFlags" attribute
462 //=======================================================================
463 bool SALOMEDS_Tool::SetFlag( const int           theFlag,
464                              SALOMEDS::Study_var theStudy,
465                              const std::string&  theEntry,
466                              const bool          theValue )
467 {
468   SALOMEDS::SObject_var anObj = theStudy->FindObjectID(theEntry.c_str());
469
470   if ( !anObj->_is_nil() )
471   {
472     SALOMEDS::GenericAttribute_var aGAttr;
473     if ( anObj->FindAttribute( aGAttr, "AttributeFlags" ) )
474     {
475       SALOMEDS::AttributeFlags_var anAttr = SALOMEDS::AttributeFlags::_narrow( aGAttr );
476       anAttr->Set( theFlag, theValue );
477     }
478     else if ( theValue )
479     {
480       SALOMEDS::StudyBuilder_var aBuilder = theStudy->NewBuilder();
481       SALOMEDS::AttributeFlags_var anAttr = SALOMEDS::AttributeFlags::_narrow(
482         aBuilder->FindOrCreateAttribute( anObj, "AttributeFlags" ) );
483       anAttr->Set( theFlag, theValue );
484     }
485     return true;
486   }
487
488   return false;
489 }
490
491 //=======================================================================
492 // name    : getAllChildren
493 // Purpose : Get all children of object.
494 //           If theObj is null all objects of study are returned
495 //=======================================================================
496 void SALOMEDS_Tool::GetAllChildren( SALOMEDS::Study_var               theStudy,
497                                     SALOMEDS::SObject_var             theObj,
498                                     std::list<SALOMEDS::SObject_var>& theList )
499 {
500   if ( theObj->_is_nil() )
501   {
502     SALOMEDS::SComponentIterator_var anIter = theStudy->NewComponentIterator();
503     for ( ; anIter->More(); anIter->Next() )
504     {
505       SALOMEDS::SObject_var anObj = SALOMEDS::SObject::_narrow( anIter->Value() );
506       if ( !anObj->_is_nil() )
507       {
508         theList.push_back( anObj );
509         GetAllChildren( theStudy, anObj, theList );
510       }
511     }
512   }
513   else
514   {
515     SALOMEDS::ChildIterator_var anIter = theStudy->NewChildIterator( theObj );
516     for ( ; anIter->More(); anIter->Next() )
517     {
518       SALOMEDS::SObject_var anObj = anIter->Value();
519       SALOMEDS::SObject_var aRef;
520       if ( !anObj->ReferencedObject( aRef ) )
521       {
522         theList.push_back( anObj );
523         GetAllChildren( theStudy, anObj, theList );
524       }
525     }
526   }
527 }
528
529