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