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