0030872: In case of failure, retry to acquire the driver for the format
[occt.git] / src / CDF / CDF_Application.cxx
1 // Created on: 1997-08-08
2 // Created by: Jean-Louis Frenkel
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified by rmi, Wed Jan 14 08:17:35 1998
18
19 #include <CDF_Application.hxx>
20 #include <CDF_Directory.hxx>
21 #include <CDF_MetaDataDriver.hxx>
22 #include <CDF_Session.hxx>
23 #include <CDM_CanCloseStatus.hxx>
24 #include <CDM_Document.hxx>
25 #include <CDM_MetaData.hxx>
26 #include <PCDM_Reader.hxx>
27 #include <PCDM_ReadWriter.hxx>
28 #include <PCDM_RetrievalDriver.hxx>
29 #include <PCDM_StorageDriver.hxx>
30 #include <Plugin.hxx>
31 #include <Standard_ErrorHandler.hxx>
32 #include <Standard_GUID.hxx>
33 #include <Standard_NoSuchObject.hxx>
34 #include <Standard_ProgramError.hxx>
35 #include <UTL.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(CDF_Application,CDM_Application)
38
39 #define theMetaDataDriver CDF_Session::CurrentSession()->MetaDataDriver()
40
41
42 //=======================================================================
43 //function : 
44 //purpose  : 
45 //=======================================================================
46 CDF_Application::CDF_Application():myRetrievableStatus(PCDM_RS_OK) {}
47
48 //=======================================================================
49 //function : Load
50 //purpose  : 
51 //=======================================================================
52 Handle(CDF_Application) CDF_Application::Load(const Standard_GUID& aGUID) {
53   return Handle(CDF_Application)::DownCast(Plugin::Load(aGUID));
54 }
55
56 //=======================================================================
57 //function : Open
58 //purpose  : 
59 //=======================================================================
60 void CDF_Application::Open(const Handle(CDM_Document)& aDocument) {
61   CDF_Session::CurrentSession()->Directory()->Add(aDocument);
62   aDocument->Open(this);
63   Activate(aDocument,CDF_TOA_New);
64 }
65
66 //=======================================================================
67 //function : CanClose
68 //purpose  : 
69 //=======================================================================
70 CDM_CanCloseStatus CDF_Application::CanClose(const Handle(CDM_Document)& aDocument) {
71   return aDocument->CanClose();
72 }
73
74 //=======================================================================
75 //function : Close
76 //purpose  : 
77 //=======================================================================
78 void CDF_Application::Close(const Handle(CDM_Document)& aDocument) {
79   CDF_Session::CurrentSession()->Directory()->Remove(aDocument);
80   aDocument->Close();
81 }
82
83 //=======================================================================
84 //function : Retrieve
85 //purpose  : 
86 //=======================================================================
87 Handle(CDM_Document) CDF_Application::Retrieve(const TCollection_ExtendedString& aFolder, 
88                                      const TCollection_ExtendedString& aName, 
89                                      const Standard_Boolean UseStorageConfiguration) {
90   TCollection_ExtendedString nullVersion;
91   return Retrieve(aFolder,aName,nullVersion,UseStorageConfiguration);
92 }
93
94 //=======================================================================
95 //function : Retrieve
96 //purpose  : 
97 //=======================================================================
98 Handle(CDM_Document)  CDF_Application::Retrieve(const TCollection_ExtendedString& aFolder, 
99                                      const TCollection_ExtendedString& aName,
100                                      const TCollection_ExtendedString& aVersion,
101                                      const Standard_Boolean UseStorageConfiguration)
102 {
103   Handle(CDM_MetaData) theMetaData; 
104   
105   if(aVersion.Length() == 0) 
106     theMetaData=theMetaDataDriver->MetaData(aFolder,aName);
107   else 
108     theMetaData=theMetaDataDriver->MetaData(aFolder,aName,aVersion);
109
110   CDF_TypeOfActivation theTypeOfActivation=TypeOfActivation(theMetaData);
111   Handle(CDM_Document) theDocument=Retrieve(theMetaData,UseStorageConfiguration,Standard_False);
112
113   CDF_Session::CurrentSession()->Directory()->Add(theDocument);
114   Activate(theDocument,theTypeOfActivation);
115
116   theDocument->Open(this);
117   return theDocument;
118 }
119
120 //=======================================================================
121 //function : CanRetrieve
122 //purpose  : 
123 //=======================================================================
124 PCDM_ReaderStatus CDF_Application::CanRetrieve(const TCollection_ExtendedString& aFolder, const TCollection_ExtendedString&  aName) {
125  TCollection_ExtendedString aVersion;
126  return CanRetrieve(aFolder,aName,aVersion);
127 }
128
129 //=======================================================================
130 //function : CanRetrieve
131 //purpose  : 
132 //=======================================================================
133 PCDM_ReaderStatus CDF_Application::CanRetrieve(const TCollection_ExtendedString&  aFolder, const TCollection_ExtendedString&  aName, const TCollection_ExtendedString&  aVersion) {
134   
135   if (!theMetaDataDriver->Find(aFolder,aName,aVersion))
136     return PCDM_RS_UnknownDocument;
137   else if (!theMetaDataDriver->HasReadPermission(aFolder,aName,aVersion))
138     return PCDM_RS_PermissionDenied;
139   else {
140     Handle(CDM_MetaData) theMetaData = theMetaDataDriver->MetaData(aFolder,aName,aVersion);
141
142     if(theMetaData->IsRetrieved()) {
143       return theMetaData->Document()->IsModified()
144         ? PCDM_RS_AlreadyRetrievedAndModified : PCDM_RS_AlreadyRetrieved;
145     }
146     else {
147       TCollection_ExtendedString theFileName=theMetaData->FileName();
148       TCollection_ExtendedString theFormat=PCDM_ReadWriter::FileFormat(theFileName);
149       if(theFormat.Length()==0) {
150         TCollection_ExtendedString ResourceName=UTL::Extension(theFileName);
151         ResourceName+=".FileFormat";
152         if(UTL::Find(Resources(),ResourceName))  {
153           theFormat=UTL::Value(Resources(),ResourceName);
154         }
155         else
156           return PCDM_RS_UnrecognizedFileFormat;
157       }
158
159       // check actual availability of the driver
160       try {
161         Handle(PCDM_Reader) aReader = ReaderFromFormat(theFormat);
162         if (aReader.IsNull())
163           return PCDM_RS_NoDriver;
164       }
165       catch (Standard_Failure const&)
166       {
167         // no need to report error, this was just check for availability
168       }
169     }
170   }
171   return PCDM_RS_OK;
172 }
173
174 //=======================================================================
175 //function : Activate
176 //purpose  : 
177 //=======================================================================
178 //void CDF_Application::Activate(const Handle(CDM_Document)& aDocument,const CDF_TypeOfActivation aTypeOfActivation) {
179 void CDF_Application::Activate(const Handle(CDM_Document)& ,const CDF_TypeOfActivation ) {
180 }
181
182 //=======================================================================
183 //function : DefaultFolder
184 //purpose  : 
185 //=======================================================================
186 Standard_ExtString CDF_Application::DefaultFolder(){
187   if(myDefaultFolder.Length() == 0) {
188     myDefaultFolder=CDF_Session::CurrentSession()->MetaDataDriver()->DefaultFolder();
189   }
190   return myDefaultFolder.ToExtString();
191 }
192
193 //=======================================================================
194 //function : SetDefaultFolder
195 //purpose  : 
196 //=======================================================================
197 Standard_Boolean CDF_Application::SetDefaultFolder(const Standard_ExtString aFolder) {
198   Standard_Boolean found = CDF_Session::CurrentSession()->MetaDataDriver()->FindFolder(aFolder);
199   if(found) myDefaultFolder=aFolder;
200   return found;
201 }
202
203 //=======================================================================
204 //function : Retrieve
205 //purpose  : 
206 //=======================================================================
207 Handle(CDM_Document) CDF_Application::Retrieve(const Handle(CDM_MetaData)& aMetaData,const Standard_Boolean UseStorageConfiguration) {
208   return Retrieve(aMetaData,UseStorageConfiguration,Standard_True);
209
210
211 //=======================================================================
212 //function : Retrieve
213 //purpose  : 
214 //=======================================================================
215 Handle(CDM_Document) CDF_Application::Retrieve(const Handle(CDM_MetaData)& aMetaData,const Standard_Boolean UseStorageConfiguration, const Standard_Boolean IsComponent) {
216   
217   Handle(CDM_Document) theDocumentToReturn;
218   myRetrievableStatus = PCDM_RS_DriverFailure;
219   if(IsComponent) {
220     Standard_SStream aMsg;
221     switch (CanRetrieve(aMetaData)) {
222     case PCDM_RS_UnknownDocument: 
223       aMsg << "could not find the referenced document: " << aMetaData->Path() << "; not found."  <<(char)0 << endl;
224       myRetrievableStatus = PCDM_RS_UnknownDocument;
225       throw Standard_Failure(aMsg.str().c_str());
226       break;
227     case PCDM_RS_PermissionDenied:      
228       aMsg << "Could not find the referenced document: " << aMetaData->Path() << "; permission denied. " <<(char)0 << endl;
229       myRetrievableStatus = PCDM_RS_PermissionDenied;
230       throw Standard_Failure(aMsg.str().c_str());
231       break;
232     default:
233       break;
234     }
235     
236   }
237   Standard_Boolean AlreadyRetrieved=aMetaData->IsRetrieved();
238   if(AlreadyRetrieved) myRetrievableStatus = PCDM_RS_AlreadyRetrieved;
239   Standard_Boolean Modified=AlreadyRetrieved && aMetaData->Document()->IsModified();
240   if(Modified) myRetrievableStatus = PCDM_RS_AlreadyRetrievedAndModified;
241   if(!AlreadyRetrieved || Modified)
242   {
243     TCollection_ExtendedString aFormat;
244     if (!Format(aMetaData->FileName(), aFormat))
245     {
246       Standard_SStream aMsg;
247       aMsg << "Could not determine format for the file " << aMetaData->FileName() << (char)0;
248       throw Standard_NoSuchObject(aMsg.str().c_str());
249     }
250     Handle(PCDM_Reader) theReader = ReaderFromFormat (aFormat);
251         
252     Handle(CDM_Document) theDocument;
253
254     if(Modified)  {
255       theDocument=aMetaData->Document();
256       theDocument->RemoveAllReferences();
257     }
258     else
259       theDocument=theReader->CreateDocument();
260     
261     SetReferenceCounter(theDocument,PCDM_RetrievalDriver::ReferenceCounter(aMetaData->FileName(), MessageDriver()));
262     
263     SetDocumentVersion(theDocument,aMetaData);
264     theMetaDataDriver->ReferenceIterator()->LoadReferences(theDocument,aMetaData,this,UseStorageConfiguration);
265
266     try {    
267       OCC_CATCH_SIGNALS
268       theReader->Read(aMetaData->FileName(),theDocument,this);
269     } 
270     catch (Standard_Failure const& anException) {
271       myRetrievableStatus = theReader->GetStatus();
272       if(myRetrievableStatus  > PCDM_RS_AlreadyRetrieved){
273         Standard_SStream aMsg;
274         aMsg << anException << endl;
275         throw Standard_Failure(aMsg.str().c_str());
276       } 
277     }
278     myRetrievableStatus = theReader->GetStatus();    
279     theDocument->SetMetaData(aMetaData);
280
281     theDocumentToReturn=theDocument;
282   }
283   else
284     theDocumentToReturn=aMetaData->Document();
285   
286   return theDocumentToReturn;
287 }
288
289 //=======================================================================
290 //function : DocumentVersion
291 //purpose  : 
292 //=======================================================================
293 Standard_Integer CDF_Application::DocumentVersion(const Handle(CDM_MetaData)& theMetaData) {
294 //  const Handle(CDM_MessageDriver)& aMsgDriver = MessageDriver();
295   return PCDM_RetrievalDriver::DocumentVersion(theMetaData->FileName(), MessageDriver());
296 }
297
298 //=======================================================================
299 //function : TypeOfActivation
300 //purpose  : 
301 //=======================================================================
302 CDF_TypeOfActivation CDF_Application::TypeOfActivation(const Handle(CDM_MetaData)& aMetaData) {
303
304   if(aMetaData->IsRetrieved()) {
305     Handle(CDM_Document) theDocument=aMetaData->Document();
306     if(theDocument->IsOpened()) {
307       if(theDocument->IsModified())
308         return CDF_TOA_Modified;
309       else
310         return CDF_TOA_Unchanged;
311     }
312     
313     else
314       return CDF_TOA_New;
315   }
316   return CDF_TOA_New;
317 }
318
319 //=======================================================================
320 //function : Read
321 //purpose  : 
322 //=======================================================================
323 Handle(CDM_Document) CDF_Application::Read (Standard_IStream& theIStream)
324 {
325   Handle(CDM_Document) aDoc;
326   Handle(Storage_Data) dData;
327   
328   TCollection_ExtendedString aFormat;
329
330   try
331   {
332     OCC_CATCH_SIGNALS
333     
334     aFormat = PCDM_ReadWriter::FileFormat (theIStream, dData);
335   }
336   catch (Standard_Failure const& anException)
337   {
338     myRetrievableStatus = PCDM_RS_FormatFailure;
339     
340     Standard_SStream aMsg;
341     aMsg << anException << endl;
342     throw Standard_Failure(aMsg.str().c_str());
343   }
344
345   if (aFormat.IsEmpty())
346   {
347     myRetrievableStatus = PCDM_RS_FormatFailure;
348     return aDoc;
349   }
350  
351   // 1. use a format name to detect plugin corresponding to the format to continue reading
352   Handle(PCDM_Reader) aReader = ReaderFromFormat (aFormat);
353
354   // 2. create document with the detected reader
355   aDoc = aReader->CreateDocument();
356
357   // 3. read the content of theIStream to aDoc
358   try
359   {
360     OCC_CATCH_SIGNALS
361   
362     aReader->Read (theIStream, dData, aDoc, this);
363   }
364   catch (Standard_Failure const& anException)
365   {
366     myRetrievableStatus = aReader->GetStatus();
367     if (myRetrievableStatus  > PCDM_RS_AlreadyRetrieved)
368     {
369       Standard_SStream aMsg;
370       aMsg << anException << endl;
371       throw Standard_Failure(aMsg.str().c_str());
372     }   
373   }
374
375   myRetrievableStatus = aReader->GetStatus();
376
377   return aDoc;
378 }
379
380 //=======================================================================
381 //function : ReaderFromFormat
382 //purpose  : 
383 //=======================================================================
384 Handle(PCDM_Reader) CDF_Application::ReaderFromFormat(const TCollection_ExtendedString& theFormat)
385 {
386   // check map of readers
387   Handle(PCDM_RetrievalDriver) aReader;
388   if (myReaders.FindFromKey (theFormat, aReader))
389     return aReader;
390
391   // support of legacy method of loading reader as plugin
392   TCollection_ExtendedString aResourceName = theFormat;
393   aResourceName += ".RetrievalPlugin";
394   if (!UTL::Find(Resources(), aResourceName))
395   {
396     Standard_SStream aMsg; 
397     aMsg << "Could not found the item:" << aResourceName <<(char)0;
398     myRetrievableStatus = PCDM_RS_WrongResource;
399     throw Standard_NoSuchObject(aMsg.str().c_str());
400   }
401
402   // Get GUID as a string.
403   TCollection_ExtendedString strPluginId = UTL::Value(Resources(), aResourceName);
404     
405   // If the GUID (as a string) contains blanks, remove them.
406   if (strPluginId.Search(' ') != -1)
407     strPluginId.RemoveAll(' ');
408     
409   // Convert to GUID.
410   Standard_GUID aPluginId = UTL::GUID(strPluginId);
411
412   try {
413     OCC_CATCH_SIGNALS
414     aReader = Handle(PCDM_RetrievalDriver)::DownCast(Plugin::Load(aPluginId));  
415   } 
416   catch (Standard_Failure const& anException)
417   {
418     myRetrievableStatus = PCDM_RS_WrongResource;
419     throw anException;
420   }     
421   if (!aReader.IsNull()) {
422     aReader->SetFormat(theFormat);
423   }
424   else
425   {
426     myRetrievableStatus = PCDM_RS_WrongResource;
427   }
428
429   // record in map
430   myReaders.Add(theFormat, aReader);
431   return aReader;
432 }
433
434 //=======================================================================
435 //function : WriterFromFormat
436 //purpose  : 
437 //=======================================================================
438 Handle(PCDM_StorageDriver) CDF_Application::WriterFromFormat(const TCollection_ExtendedString& theFormat)
439 {  
440   // check map of writers
441   Handle(PCDM_StorageDriver) aDriver;
442   if (myWriters.FindFromKey(theFormat, aDriver))
443     return aDriver;
444
445   // support of legacy method of loading reader as plugin
446   TCollection_ExtendedString aResourceName = theFormat;
447   aResourceName += ".StoragePlugin";  
448   if(!UTL::Find(Resources(), aResourceName))
449   {
450     myWriters.Add(theFormat, aDriver);
451     Standard_SStream aMsg; 
452     aMsg << "Could not found the resource definition:" << aResourceName <<(char)0;
453     throw Standard_NoSuchObject(aMsg.str().c_str());
454   }
455
456   // Get GUID as a string.
457   TCollection_ExtendedString strPluginId = UTL::Value(Resources(), aResourceName);
458     
459   // If the GUID (as a string) contains blanks, remove them.
460   if (strPluginId.Search(' ') != -1)
461     strPluginId.RemoveAll(' ');
462     
463   // Convert to GUID.
464   Standard_GUID aPluginId = UTL::GUID(strPluginId);
465
466   try {
467     OCC_CATCH_SIGNALS
468     aDriver = Handle(PCDM_StorageDriver)::DownCast(Plugin::Load(aPluginId));
469   } 
470   catch (Standard_Failure const& anException)
471   {
472     myWriters.Add(theFormat, aDriver);
473     myRetrievableStatus = PCDM_RS_WrongResource;
474     throw anException;
475   }     
476   if (aDriver.IsNull()) 
477   {
478     myRetrievableStatus = PCDM_RS_WrongResource;
479   }
480   else
481   {
482     aDriver->SetFormat(theFormat);
483   }
484
485   // record in map
486   myWriters.Add(theFormat, aDriver);
487   return aDriver;
488 }
489
490 //=======================================================================
491 //function : Format
492 //purpose  : dp 
493 //=======================================================================
494 Standard_Boolean CDF_Application::Format(const TCollection_ExtendedString& aFileName, 
495                                          TCollection_ExtendedString& theFormat)
496 {
497   
498   theFormat = PCDM_ReadWriter::FileFormat(aFileName);
499 // It is good if the format is in the file. Otherwise base on the extension.
500   if(theFormat.Length()==0) {
501     TCollection_ExtendedString ResourceName;
502     ResourceName=UTL::Extension(aFileName);
503     ResourceName+=".FileFormat";
504     
505     if(UTL::Find(Resources(),ResourceName))  {
506       theFormat = UTL::Value(Resources(),ResourceName);
507     }
508     else return Standard_False;
509   }
510   return Standard_True;
511 }
512
513 //=======================================================================
514 //function : CanRetrieve
515 //purpose  : 
516 //=======================================================================
517 PCDM_ReaderStatus CDF_Application::CanRetrieve(const Handle(CDM_MetaData)& aMetaData) {
518   if(aMetaData->HasVersion())
519     return CanRetrieve(aMetaData->Folder(),aMetaData->Name(),aMetaData->Version());
520   else
521     return CanRetrieve(aMetaData->Folder(),aMetaData->Name());
522 }