bump product version to 4.1.6.2
[LibreOffice.git] / xmloff / source / meta / xmlversion.cxx
blob815b47fcf5428316d10c1917b2432226c778fb32
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/ElementModes.hpp>
21 #include <tools/debug.hxx>
22 #include <unotools/streamwrap.hxx>
23 #include <xmlversion.hxx>
24 #include <xmloff/xmlmetae.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <comphelper/componentcontext.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <com/sun/star/io/XActiveDataSource.hpp>
30 #include <com/sun/star/io/XOutputStream.hpp>
31 #include <com/sun/star/util/DateTime.hpp>
32 #include <com/sun/star/util/MeasureUnit.hpp>
33 #include <com/sun/star/xml/sax/InputSource.hpp>
34 #include <com/sun/star/xml/sax/Parser.hpp>
35 #include <com/sun/star/xml/sax/Writer.hpp>
37 using namespace ::com::sun::star::xml::sax;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star;
41 // ------------------------------------------------------------------------
43 const char XMLN_VERSIONSLIST[] = "VersionList.xml";
45 // ------------------------------------------------------------------------
46 // #110897#
47 XMLVersionListExport::XMLVersionListExport(
48 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext,
49 const com::sun::star::uno::Sequence < com::sun::star::util::RevisionTag >& rVersions,
50 const OUString &rFileName,
51 Reference< XDocumentHandler > &rHandler )
52 : SvXMLExport( xContext, rFileName, util::MeasureUnit::CM, rHandler ),
53 maVersions( rVersions )
55 _GetNamespaceMap().AddAtIndex( XML_NAMESPACE_DC_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_DC),
56 xmloff::token::GetXMLToken(xmloff::token::XML_N_DC), XML_NAMESPACE_DC );
57 _GetNamespaceMap().AddAtIndex( XML_NAMESPACE_FRAMEWORK_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_VERSIONS_LIST),
58 xmloff::token::GetXMLToken(xmloff::token::XML_N_VERSIONS_LIST), XML_NAMESPACE_FRAMEWORK );
61 // ------------------------------------------------------------------------
62 sal_uInt32 XMLVersionListExport::exportDoc( enum ::xmloff::token::XMLTokenEnum )
64 GetDocHandler()->startDocument();
66 addChaffWhenEncryptedStorage();
68 sal_uInt16 nPos = _GetNamespaceMap().GetIndexByKey( XML_NAMESPACE_DC );
70 AddAttribute( XML_NAMESPACE_NONE, _GetNamespaceMap().GetAttrNameByIndex( nPos ),
71 _GetNamespaceMap().GetNameByIndex ( nPos ) );
73 nPos = _GetNamespaceMap().GetIndexByKey( XML_NAMESPACE_FRAMEWORK );
74 AddAttribute( XML_NAMESPACE_NONE, _GetNamespaceMap().GetAttrNameByIndex( nPos ),
75 _GetNamespaceMap().GetNameByIndex ( nPos ) );
78 // the following object will write all collected attributes in its dtor
79 SvXMLElementExport aRoot( *this, XML_NAMESPACE_FRAMEWORK, xmloff::token::XML_VERSION_LIST, sal_True, sal_True );
81 for ( sal_Int32 n=0; n<maVersions.getLength(); n++ )
83 const util::RevisionTag& rInfo = maVersions[n];
84 AddAttribute( XML_NAMESPACE_FRAMEWORK,
85 xmloff::token::XML_TITLE,
86 OUString( rInfo.Identifier ) );
87 AddAttribute( XML_NAMESPACE_FRAMEWORK,
88 xmloff::token::XML_COMMENT,
89 OUString( rInfo.Comment ) );
90 AddAttribute( XML_NAMESPACE_FRAMEWORK,
91 xmloff::token::XML_CREATOR,
92 OUString( rInfo.Author ) );
94 OUString aDateStr =
95 SvXMLMetaExport::GetISODateTimeString( rInfo.TimeStamp );
97 AddAttribute( XML_NAMESPACE_DC, xmloff::token::XML_DATE_TIME, aDateStr );
99 // the following object will write all collected attributes in its dtor
100 SvXMLElementExport aEntry( *this, XML_NAMESPACE_FRAMEWORK, xmloff::token::XML_VERSION_ENTRY, sal_True, sal_True );
103 GetDocHandler()->endDocument();
104 return 0;
107 // ------------------------------------------------------------------------
108 XMLVersionListImport::XMLVersionListImport(
109 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext,
110 com::sun::star::uno::Sequence < com::sun::star::util::RevisionTag >& rVersions )
111 : SvXMLImport(xContext),
112 maVersions( rVersions )
114 GetNamespaceMap().AddAtIndex( XML_NAMESPACE_FRAMEWORK_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_VERSIONS_LIST),
115 xmloff::token::GetXMLToken(xmloff::token::XML_N_VERSIONS_LIST), XML_NAMESPACE_FRAMEWORK );
118 // ------------------------------------------------------------------------
119 XMLVersionListImport::~XMLVersionListImport( void ) throw()
122 // ------------------------------------------------------------------------
123 SvXMLImportContext *XMLVersionListImport::CreateContext(
124 sal_uInt16 nPrefix,
125 const OUString& rLocalName,
126 const Reference< XAttributeList > & xAttrList )
128 SvXMLImportContext *pContext = 0;
130 if ( XML_NAMESPACE_FRAMEWORK == nPrefix &&
131 rLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_VERSION_LIST) )
133 pContext = new XMLVersionListContext( *this, nPrefix, rLocalName, xAttrList );
135 else
137 pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
140 return pContext;
144 // ------------------------------------------------------------------------
145 XMLVersionListContext::XMLVersionListContext( XMLVersionListImport& rImport,
146 sal_uInt16 nPrefix,
147 const OUString& rLocalName,
148 const Reference< XAttributeList > & )
149 : SvXMLImportContext( rImport, nPrefix, rLocalName )
150 , rLocalRef( rImport )
154 // ------------------------------------------------------------------------
155 XMLVersionListContext::~XMLVersionListContext( void )
158 // ------------------------------------------------------------------------
159 SvXMLImportContext *XMLVersionListContext::CreateChildContext( sal_uInt16 nPrefix,
160 const OUString& rLocalName,
161 const Reference< XAttributeList > & xAttrList )
163 SvXMLImportContext *pContext = 0;
165 if ( nPrefix == XML_NAMESPACE_FRAMEWORK &&
166 rLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_VERSION_ENTRY) )
168 pContext = new XMLVersionContext( rLocalRef, nPrefix, rLocalName, xAttrList );
170 else
172 pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName );
175 return pContext;
178 // ------------------------------------------------------------------------
179 XMLVersionContext::XMLVersionContext( XMLVersionListImport& rImport,
180 sal_uInt16 nPref,
181 const OUString& rLocalName,
182 const Reference< XAttributeList > & xAttrList )
183 : SvXMLImportContext( rImport, nPref, rLocalName )
184 , rLocalRef( rImport )
186 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
188 if ( !nAttrCount )
189 return;
191 util::RevisionTag aInfo;
192 for ( sal_Int16 i=0; i < nAttrCount; i++ )
194 OUString aLocalName;
195 const OUString& rAttrName = xAttrList->getNameByIndex( i );
196 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
198 if ( XML_NAMESPACE_FRAMEWORK == nPrefix )
200 if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_TITLE) )
202 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
203 aInfo.Identifier = rAttrValue;
205 else if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_COMMENT) )
207 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
208 aInfo.Comment = rAttrValue;
210 else if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_CREATOR) )
212 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
213 aInfo.Author = rAttrValue;
216 else if ( ( XML_NAMESPACE_DC == nPrefix ) &&
217 ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_DATE_TIME) ) )
219 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
220 util::DateTime aTime;
221 if ( ParseISODateTimeString( rAttrValue, aTime ) )
222 aInfo.TimeStamp = aTime;
226 uno::Sequence < util::RevisionTag >& aList = rLocalRef.GetList();
227 sal_Int32 nLength = aList.getLength();
228 aList.realloc( nLength+1 );
229 aList[nLength] = aInfo;
233 // ------------------------------------------------------------------------
234 XMLVersionContext::~XMLVersionContext( void )
237 // ------------------------------------------------------------------------
238 sal_Bool XMLVersionContext::ParseISODateTimeString(
239 const OUString& rString,
240 util::DateTime& rDateTime )
242 sal_Bool bSuccess = sal_True;
244 OUString aDateStr, aTimeStr;
245 sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' );
246 if ( nPos >= 0 )
248 aDateStr = rString.copy( 0, nPos );
249 aTimeStr = rString.copy( nPos + 1 );
251 else
252 aDateStr = rString; // no separator: only date part
254 sal_Int32 nYear = 0;
255 sal_Int32 nMonth = 1;
256 sal_Int32 nDay = 1;
257 sal_Int32 nHour = 0;
258 sal_Int32 nMin = 0;
259 sal_Int32 nSec = 0;
261 const sal_Unicode* pStr = aDateStr.getStr();
262 sal_Int32 nDateTokens = 1;
263 while ( *pStr )
265 if ( *pStr == '-' )
266 nDateTokens++;
267 pStr++;
269 if ( nDateTokens > 3 || aDateStr.isEmpty() )
270 bSuccess = sal_False;
271 else
273 sal_Int32 n = 0;
274 nYear = aDateStr.getToken( 0, '-', n ).toInt32();
275 if ( nYear > 9999 )
276 bSuccess = sal_False;
277 else if ( nDateTokens >= 2 )
279 nMonth = aDateStr.getToken( 0, '-', n ).toInt32();
280 if ( nMonth > 12 )
281 bSuccess = sal_False;
282 else if ( nDateTokens >= 3 )
284 nDay = aDateStr.getToken( 0, '-', n ).toInt32();
285 if ( nDay > 31 )
286 bSuccess = sal_False;
291 if ( bSuccess && !aTimeStr.isEmpty() ) // time is optional
293 pStr = aTimeStr.getStr();
294 sal_Int32 nTimeTokens = 1;
295 while ( *pStr )
297 if ( *pStr == ':' )
298 nTimeTokens++;
299 pStr++;
301 if ( nTimeTokens > 3 )
302 bSuccess = sal_False;
303 else
305 sal_Int32 n = 0;
306 nHour = aTimeStr.getToken( 0, ':', n ).toInt32();
307 if ( nHour > 23 )
308 bSuccess = sal_False;
309 else if ( nTimeTokens >= 2 )
311 nMin = aTimeStr.getToken( 0, ':', n ).toInt32();
312 if ( nMin > 59 )
313 bSuccess = sal_False;
314 else if ( nTimeTokens >= 3 )
316 nSec = aTimeStr.getToken( 0, ':', n ).toInt32();
317 if ( nSec > 59 )
318 bSuccess = sal_False;
324 if ( bSuccess )
326 rDateTime.Day = sal::static_int_cast< sal_uInt16 >(nDay);
327 rDateTime.Month = sal::static_int_cast< sal_uInt16 >(nMonth);
328 rDateTime.Year = sal::static_int_cast< sal_uInt16 >(nYear);
329 rDateTime.Hours = sal::static_int_cast< sal_uInt16 >(nHour);
330 rDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(nMin);
331 rDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(nSec);
334 return bSuccess;
338 // ------------------------------------------------------------------------
339 void SAL_CALL XMLVersionListPersistence::store( const uno::Reference< embed::XStorage >& xRoot, const uno::Sequence< util::RevisionTag >& rVersions )
340 throw (::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
342 // no storage, no version list!
343 if ( xRoot.is() )
345 // get the services needed for writing the xml data
346 Reference< uno::XComponentContext > xContext =
347 comphelper::getProcessComponentContext();
349 Reference< XWriter > xWriter = Writer::create(xContext);
351 // check whether there's already a sub storage with the version info
352 // and delete it
353 OUString sVerName( XMLN_VERSIONSLIST );
355 try {
356 // open (create) the sub storage with the version info
357 uno::Reference< io::XStream > xVerStream = xRoot->openStreamElement(
358 sVerName,
359 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
360 if ( !xVerStream.is() )
361 throw uno::RuntimeException();
363 Reference< io::XOutputStream > xOut = xVerStream->getOutputStream();
364 if ( !xOut.is() )
365 throw uno::RuntimeException(); // the stream was successfully opened for writing already
367 Reference< io::XActiveDataSource > xSrc( xWriter, uno::UNO_QUERY );
368 xSrc->setOutputStream(xOut);
370 Reference< XDocumentHandler > xHandler( xWriter, uno::UNO_QUERY );
372 XMLVersionListExport aExp( xContext, rVersions, sVerName, xHandler );
374 aExp.exportDoc( ::xmloff::token::XML_VERSION );
376 xVerStream = uno::Reference< io::XStream >(); // use refcounting for now to dispose
378 catch( uno::Exception& )
380 // TODO: error handling
385 // ------------------------------------------------------------------------
386 uno::Sequence< util::RevisionTag > SAL_CALL XMLVersionListPersistence::load( const uno::Reference< embed::XStorage >& xRoot )
387 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
389 com::sun::star::uno::Sequence < com::sun::star::util::RevisionTag > aVersions;
391 const OUString sDocName( XMLN_VERSIONSLIST );
392 uno::Reference< container::XNameAccess > xRootNames( xRoot, uno::UNO_QUERY );
394 try {
395 if ( xRootNames.is() && xRootNames->hasByName( sDocName ) && xRoot->isStreamElement( sDocName ) )
397 Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
399 InputSource aParserInput;
401 uno::Reference< beans::XPropertySet > xProps( xRoot, uno::UNO_QUERY );
402 OSL_ENSURE( xProps.is(), "Storage must implement XPropertySet!\n" );
403 if ( xProps.is() )
405 try {
406 xProps->getPropertyValue( OUString("URL") ) >>= aParserInput.sSystemId;
408 catch( uno::Exception& )
412 uno::Reference< io::XStream > xDocStream = xRoot->openStreamElement(
413 sDocName,
414 embed::ElementModes::READ );
415 if ( !xDocStream.is() )
416 throw uno::RuntimeException();
418 aParserInput.aInputStream = xDocStream->getInputStream();
419 OSL_ENSURE( aParserInput.aInputStream.is(),
420 "The stream was successfully opened for reading, the input part must be accessible!\n" );
421 if ( !aParserInput.aInputStream.is() )
422 throw uno::RuntimeException();
424 // get filter
425 Reference< XDocumentHandler > xFilter = new XMLVersionListImport( xContext, aVersions );
427 // connect parser and filter
428 Reference< XParser > xParser = xml::sax::Parser::create(xContext);
429 xParser->setDocumentHandler( xFilter );
431 // parse
434 xParser->parseStream( aParserInput );
436 catch( SAXParseException& ) {}
437 catch( SAXException& ) {}
438 catch( io::IOException& ) {}
441 catch( uno::Exception& )
443 // TODO: error handling
446 return aVersions;
449 uno::Sequence< OUString > SAL_CALL XMLVersionListPersistence_getSupportedServiceNames()
450 throw()
452 const OUString aServiceName(
453 "com.sun.star.document.DocumentRevisionListPersistence" );
454 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
455 return aSeq;
458 OUString SAL_CALL XMLVersionListPersistence_getImplementationName() throw()
460 return OUString( "XMLVersionListPersistence" );
463 uno::Reference< uno::XInterface > SAL_CALL XMLVersionListPersistence_createInstance(
464 const uno::Reference< lang::XMultiServiceFactory > &)
465 throw( uno::Exception )
467 return (cppu::OWeakObject*)new XMLVersionListPersistence;
470 uno::Sequence< OUString > SAL_CALL XMLVersionImExportOOO_getSupportedServiceNames()
471 throw()
473 const OUString aServiceName(
474 "com.sun.star.document.DocumentRevisionListPersistence" );
475 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
476 return aSeq;
479 OUString SAL_CALL XMLVersionImExportOOO_getImplementationName() throw()
481 return OUString( "XMLVersionImExportOOo" );
484 uno::Reference< uno::XInterface > SAL_CALL XMLVersionImExportOOO_createInstance(
485 const uno::Reference< lang::XMultiServiceFactory > &)
486 throw( uno::Exception )
488 return (cppu::OWeakObject*)new XMLVersionListPersistence;
491 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */