0029195: OCAF - ensure thread safety for different documents.
[occt.git] / src / PCDM / PCDM_ReadWriter.cxx
1 // Created on: 1997-12-09
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
18 #include <CDM_Document.hxx>
19 #include <PCDM.hxx>
20 #include <PCDM_DOMHeaderParser.hxx>
21 #include <PCDM_ReadWriter.hxx>
22 #include <PCDM_ReadWriter_1.hxx>
23 #include <Standard_ErrorHandler.hxx>
24 #include <Standard_Type.hxx>
25 #include <Storage_BaseDriver.hxx>
26 #include <Storage_Data.hxx>
27 #include <Storage_HeaderData.hxx>
28 #include <Storage_TypeData.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TCollection_ExtendedString.hxx>
31 #include <TColStd_HSequenceOfAsciiString.hxx>
32 #include <UTL.hxx>
33
34 IMPLEMENT_STANDARD_RTTIEXT(PCDM_ReadWriter,Standard_Transient)
35
36 #define FILE_FORMAT "FILE_FORMAT: "
37
38 static TCollection_ExtendedString TryXmlDriverType
39                                 (const TCollection_AsciiString& theFileName);
40
41 static TCollection_ExtendedString TryXmlDriverType (Standard_IStream& theIStream);
42
43 //=======================================================================
44 //function : Open
45 //purpose  : 
46 //=======================================================================
47
48 void PCDM_ReadWriter::Open (const Handle(Storage_BaseDriver)&   aDriver,
49                             const TCollection_ExtendedString&   aFileName,
50                             const Storage_OpenMode              aMode)
51 {
52   Storage_Error error = UTL::OpenFile(aDriver,aFileName,aMode);
53   if(error != Storage_VSOk) {
54     Standard_SStream aMsg; aMsg << "could not open the file: ";
55     aMsg << aFileName;
56     switch (error) {
57     case Storage_VSOpenError: aMsg << "; file was not found or permission denied"; break;
58     case Storage_VSAlreadyOpen: aMsg<< "; file was already opened";
59     default:
60       break;
61     }
62     aMsg << (char)0;
63     throw Standard_Failure(aMsg.str().c_str());
64   }
65 }
66
67 //=======================================================================
68 //function : Reader
69 //purpose  : 
70 //=======================================================================
71
72 //Handle(PCDM_ReadWriter) PCDM_ReadWriter::Reader(const TCollection_ExtendedString& aFileName) {
73
74 Handle(PCDM_ReadWriter) PCDM_ReadWriter::Reader
75                                            (const TCollection_ExtendedString&)
76 {
77   return (new PCDM_ReadWriter_1);
78 }
79
80 //=======================================================================
81 //function : Writer
82 //purpose  : 
83 //=======================================================================
84
85 Handle(PCDM_ReadWriter) PCDM_ReadWriter::Writer ()
86 {
87   return (new PCDM_ReadWriter_1);
88 }
89  
90 //=======================================================================
91 //function : WriteFileFormat
92 //purpose  : 
93 //=======================================================================
94
95 void PCDM_ReadWriter::WriteFileFormat (const Handle(Storage_Data)& aData,
96                                        const Handle(CDM_Document)& aDocument)
97
98   TCollection_AsciiString ligne(FILE_FORMAT);
99   ligne += TCollection_AsciiString(aDocument->StorageFormat(),'?');
100
101   aData->AddToUserInfo(ligne);
102 }
103
104 //=======================================================================
105 //function : FileFormat
106 //purpose  : 
107 //=======================================================================
108
109 TCollection_ExtendedString PCDM_ReadWriter::FileFormat
110                                 (const TCollection_ExtendedString& aFileName)
111 {
112   TCollection_ExtendedString theFormat;
113   
114   Handle(Storage_BaseDriver) theFileDriver;
115
116   // conversion to UTF-8 is done inside
117   TCollection_AsciiString theFileName (aFileName);
118   if (PCDM::FileDriverType (theFileName, theFileDriver) == PCDM_TOFD_Unknown)
119     return ::TryXmlDriverType (theFileName);
120
121   Standard_Boolean theFileIsOpen(Standard_False);
122   try {
123     OCC_CATCH_SIGNALS
124     
125     Open(theFileDriver,aFileName,Storage_VSRead);
126     theFileIsOpen=Standard_True;
127     Storage_HeaderData hd;
128     hd.Read (theFileDriver);
129     const TColStd_SequenceOfAsciiString &refUserInfo = hd.UserInfo();
130     Standard_Boolean found=Standard_False;
131     for (Standard_Integer i =1; !found && i<=  refUserInfo.Length() ; i++) {
132       if(refUserInfo(i).Search(FILE_FORMAT) != -1) {
133         found=Standard_True;
134         theFormat=TCollection_ExtendedString(refUserInfo(i).Token(" ",2).ToCString(),
135                                              Standard_True);
136       }
137     }
138     if (!found)
139     {
140       Storage_TypeData td;
141       td.Read (theFileDriver);
142       theFormat = td.Types()->Value(1);
143     }
144   }
145   catch (Standard_Failure const&) {}
146   
147   if(theFileIsOpen)
148   {
149     theFileDriver->Close();
150   }
151
152   return theFormat;
153 }
154
155 //=======================================================================
156 //function : FileFormat
157 //purpose  : 
158 //=======================================================================
159
160 TCollection_ExtendedString PCDM_ReadWriter::FileFormat (Standard_IStream& theIStream, Handle(Storage_Data)& theData)
161 {
162   TCollection_ExtendedString aFormat;
163
164   Handle(Storage_BaseDriver) aFileDriver;
165   if (PCDM::FileDriverType (theIStream, aFileDriver) == PCDM_TOFD_XmlFile)
166   {
167     return ::TryXmlDriverType (theIStream);
168   }
169   if (!aFileDriver)
170   {
171     // type is not recognized, return empty string
172     return aFormat;
173   }
174
175   aFileDriver->ReadCompleteInfo (theIStream, theData);
176
177   for (Standard_Integer i = 1; i <= theData->HeaderData()->UserInfo().Length(); i++)
178   {
179     const TCollection_AsciiString& aLine = theData->HeaderData()->UserInfo().Value(i);
180
181     if(aLine.Search (FILE_FORMAT) != -1)
182     {
183       aFormat = TCollection_ExtendedString (aLine.Token(" ",2).ToCString(), Standard_True);
184     }
185   }
186
187   return aFormat;
188 }
189
190 //=======================================================================
191 //function : ::TryXmlDriverType
192 //purpose  : called from FileFormat()
193 //=======================================================================
194
195 static TCollection_ExtendedString TryXmlDriverType
196                                 (const TCollection_AsciiString& theFileName)
197 {
198   TCollection_ExtendedString theFormat;
199   PCDM_DOMHeaderParser       aParser;
200   const char                 * aDocumentElementName = "document";
201   aParser.SetStartElementName (Standard_CString(aDocumentElementName));
202
203   // Parse the file; if there is no error or an error appears before retrieval
204   // of the DocumentElement, the XML format cannot be defined
205   if (aParser.parse (theFileName.ToCString()))
206   {
207     LDOM_Element anElement = aParser.GetElement();
208     if (anElement.getTagName().equals (LDOMString(aDocumentElementName)))
209       theFormat = anElement.getAttribute ("format");
210   }
211   return theFormat;
212 }
213
214 //=======================================================================
215 //function : ::TryXmlDriverType
216 //purpose  : called from FileFormat()
217 //=======================================================================
218
219 static TCollection_ExtendedString TryXmlDriverType (Standard_IStream& theIStream)
220 {
221   TCollection_ExtendedString theFormat;
222   PCDM_DOMHeaderParser       aParser;
223   const char                 * aDocumentElementName = "document";
224   aParser.SetStartElementName (Standard_CString(aDocumentElementName));
225
226   if (theIStream.good())
227   {
228     // Parse the file; if there is no error or an error appears before retrieval
229     // of the DocumentElement, the XML format cannot be defined
230     if (aParser.parse (theIStream, Standard_True))
231     {
232       LDOM_Element anElement = aParser.GetElement();
233       if (anElement.getTagName().equals (LDOMString(aDocumentElementName)))
234         theFormat = anElement.getAttribute ("format");
235     }
236   }
237
238   return theFormat;
239 }