1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
22 #include <com/sun/star/xml/dom/SAXDocumentBuilder.hpp>
23 #include <com/sun/star/xml/dom/XSAXDocumentBuilder2.hpp>
24 #include <com/sun/star/xml/xpath/XPathAPI.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/beans/XPropertySetInfo.hpp>
27 #include <comphelper/processfactory.hxx>
28 #include <xmloff/xmlmetai.hxx>
29 #include <xmloff/xmlimp.hxx>
30 #include <xmloff/nmspmap.hxx>
31 #include <xmloff/xmltoken.hxx>
32 #include "xmloff/xmlnmspe.hxx"
35 using namespace com::sun::star
;
36 using namespace ::xmloff::token
;
39 //===========================================================================
41 /// builds a DOM tree from SAX events, by forwarding to SAXDocumentBuilder
42 class XMLDocumentBuilderContext
: public SvXMLImportContext
45 ::com::sun::star::uno::Reference
<
46 ::com::sun::star::xml::dom::XSAXDocumentBuilder2
> mxDocBuilder
;
49 XMLDocumentBuilderContext(SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
50 const OUString
& rLName
,
51 const ::com::sun::star::uno::Reference
<
52 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
,
53 const ::com::sun::star::uno::Reference
<
54 ::com::sun::star::xml::dom::XSAXDocumentBuilder2
>& rDocBuilder
);
56 virtual ~XMLDocumentBuilderContext();
58 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
59 const OUString
& rLocalName
,
60 const ::com::sun::star::uno::Reference
<
61 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
63 virtual void StartElement( const ::com::sun::star::uno::Reference
<
64 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
);
66 virtual void Characters( const OUString
& rChars
);
68 virtual void EndElement();
71 XMLDocumentBuilderContext::XMLDocumentBuilderContext(SvXMLImport
& rImport
,
72 sal_uInt16 nPrfx
, const OUString
& rLName
,
73 const uno::Reference
<xml::sax::XAttributeList
>&,
74 const uno::Reference
<xml::dom::XSAXDocumentBuilder2
>& rDocBuilder
) :
75 SvXMLImportContext( rImport
, nPrfx
, rLName
),
76 mxDocBuilder(rDocBuilder
)
80 XMLDocumentBuilderContext::~XMLDocumentBuilderContext()
85 XMLDocumentBuilderContext::CreateChildContext( sal_uInt16 nPrefix
,
86 const OUString
& rLocalName
,
87 const uno::Reference
< xml::sax::XAttributeList
>& rAttrs
)
89 return new XMLDocumentBuilderContext(
90 GetImport(), nPrefix
, rLocalName
, rAttrs
, mxDocBuilder
);
93 void XMLDocumentBuilderContext::StartElement(
94 const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
96 mxDocBuilder
->startElement(
97 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()),
101 void XMLDocumentBuilderContext::Characters( const OUString
& rChars
)
103 mxDocBuilder
->characters(rChars
);
106 void XMLDocumentBuilderContext::EndElement()
108 mxDocBuilder
->endElement(
109 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()));
113 //===========================================================================
116 lcl_initDocumentProperties(SvXMLImport
& rImport
,
117 uno::Reference
<xml::dom::XSAXDocumentBuilder2
> const& xDocBuilder
,
118 uno::Reference
<document::XDocumentProperties
> const& xDocProps
)
120 uno::Sequence
< uno::Any
> aSeq(1);
121 aSeq
[0] <<= xDocBuilder
->getDocument();
122 uno::Reference
< lang::XInitialization
> const xInit(xDocProps
,
123 uno::UNO_QUERY_THROW
);
125 xInit
->initialize(aSeq
);
126 rImport
.SetStatistics(xDocProps
->getDocumentStatistics());
127 // convert all URLs from relative to absolute
128 xDocProps
->setTemplateURL(rImport
.GetAbsoluteReference(
129 xDocProps
->getTemplateURL()));
130 xDocProps
->setAutoloadURL(rImport
.GetAbsoluteReference(
131 xDocProps
->getAutoloadURL()));
132 SvXMLMetaDocumentContext::setBuildId(
133 xDocProps
->getGenerator(), rImport
.getImportInfo());
134 } catch (const uno::RuntimeException
&) {
136 } catch (const uno::Exception
& e
) {
137 throw lang::WrappedTargetRuntimeException(
139 "SvXMLMetaDocumentContext::initDocumentProperties: "
140 "properties init exception"),
141 rImport
, makeAny(e
));
146 lcl_initGenerator(SvXMLImport
& rImport
,
147 uno::Reference
<xml::dom::XSAXDocumentBuilder2
> const& xDocBuilder
)
149 uno::Reference
< xml::dom::XDocument
> const xDoc(xDocBuilder
->getDocument(),
152 uno::Reference
< xml::xpath::XXPathAPI
> const xPath
= xml::xpath::XPathAPI::create(
153 rImport
.GetComponentContext() );
154 xPath
->registerNS(GetXMLToken(XML_NP_OFFICE
),GetXMLToken(XML_N_OFFICE
));
155 xPath
->registerNS(GetXMLToken(XML_NP_META
), GetXMLToken(XML_N_META
));
157 OUString
const expr( "string(/office:document-meta/office:meta/meta:generator)");
158 uno::Reference
< xml::xpath::XXPathObject
> const xObj(
159 xPath
->eval(xDoc
.get(), expr
), uno::UNO_SET_THROW
);
160 OUString
const value(xObj
->getString());
161 SvXMLMetaDocumentContext::setBuildId(value
, rImport
.getImportInfo());
162 } catch (const uno::RuntimeException
&) {
164 } catch (const uno::Exception
& e
) {
165 throw lang::WrappedTargetRuntimeException(
167 "SvXMLMetaDocumentContext::initGenerator: exception"),
168 rImport
, makeAny(e
));
172 SvXMLMetaDocumentContext::SvXMLMetaDocumentContext(SvXMLImport
& rImport
,
173 sal_uInt16 nPrfx
, const OUString
& rLName
,
174 const uno::Reference
<document::XDocumentProperties
>& xDocProps
) :
175 SvXMLImportContext( rImport
, nPrfx
, rLName
),
176 mxDocProps(xDocProps
),
178 xml::dom::SAXDocumentBuilder::create(
179 comphelper::getProcessComponentContext()))
181 // #i103539#: must always read meta.xml for generator, xDocProps unwanted then
182 // OSL_ENSURE(xDocProps.is(), "SvXMLMetaDocumentContext: no document props");
185 SvXMLMetaDocumentContext::~SvXMLMetaDocumentContext()
189 SvXMLImportContext
*SvXMLMetaDocumentContext::CreateChildContext(
190 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
191 const uno::Reference
<xml::sax::XAttributeList
>& rAttrs
)
193 if ( (XML_NAMESPACE_OFFICE
== nPrefix
) &&
194 IsXMLToken(rLocalName
, XML_META
) )
196 return new XMLDocumentBuilderContext(
197 GetImport(), nPrefix
, rLocalName
, rAttrs
, mxDocBuilder
);
201 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
206 void SvXMLMetaDocumentContext::StartElement(
207 const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
209 mxDocBuilder
->startDocument();
210 // hardcode office:document-meta (necessary in case of flat file ODF)
211 mxDocBuilder
->startElement(
212 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(),
213 GetXMLToken(XML_DOCUMENT_META
)), xAttrList
);
217 void SvXMLMetaDocumentContext::EndElement()
219 // hardcode office:document-meta (necessary in case of flat file ODF)
220 mxDocBuilder
->endElement(
221 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(),
222 GetXMLToken(XML_DOCUMENT_META
)));
223 mxDocBuilder
->endDocument();
226 lcl_initDocumentProperties(GetImport(), mxDocBuilder
, mxDocProps
);
230 lcl_initGenerator(GetImport(), mxDocBuilder
);
234 void SvXMLMetaDocumentContext::setBuildId(OUString
const& i_rBuildId
, const uno::Reference
<beans::XPropertySet
>& xImportInfo
)
237 // skip to second product
238 sal_Int32 nBegin
= i_rBuildId
.indexOf( ' ' );
241 // skip to build information
242 nBegin
= i_rBuildId
.indexOf( '/', nBegin
);
245 sal_Int32 nEnd
= i_rBuildId
.indexOf( 'm', nBegin
);
248 OUStringBuffer
sBuffer(
249 i_rBuildId
.copy( nBegin
+1, nEnd
-nBegin
-1 ) );
250 const OUString
sBuildCompare(
252 nBegin
= i_rBuildId
.indexOf( sBuildCompare
, nEnd
);
255 sBuffer
.append( (sal_Unicode
)'$' );
256 sBuffer
.append( i_rBuildId
.copy(
257 nBegin
+ sBuildCompare
.getLength() ) );
258 sBuildId
= sBuffer
.makeStringAndClear();
264 if ( sBuildId
.isEmpty() )
266 if ( i_rBuildId
.startsWith("StarOffice 7")
267 || i_rBuildId
.startsWith("StarSuite 7")
268 || i_rBuildId
.startsWith("OpenOffice.org 1"))
270 sBuildId
= OUString("645$8687");
272 else if (i_rBuildId
.startsWith("NeoOffice/2"))
274 sBuildId
= OUString("680$9134"); // fake NeoOffice as OpenOffice.org 2.2 release
278 if (i_rBuildId
.startsWith("LibreOffice/"))
280 OUStringBuffer sNumber
;
281 for (sal_Int32 i
= sizeof("LibreOffice/") - 1;
282 i
< i_rBuildId
.getLength(); ++i
)
284 if (isdigit(i_rBuildId
[i
]))
286 sNumber
.append(i_rBuildId
[i
]);
288 else if ('.' != i_rBuildId
[i
])
293 if (sNumber
.getLength())
295 sBuildId
+= (";" + sNumber
.makeStringAndClear());
299 if ( !sBuildId
.isEmpty() ) try
301 if( xImportInfo
.is() )
303 const OUString
aPropName("BuildId");
304 uno::Reference
< beans::XPropertySetInfo
> xSetInfo(
305 xImportInfo
->getPropertySetInfo());
306 if( xSetInfo
.is() && xSetInfo
->hasPropertyByName( aPropName
) )
307 xImportInfo
->setPropertyValue( aPropName
, uno::makeAny( sBuildId
) );
310 catch(const uno::Exception
&)
315 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */