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 .
20 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
21 #include <com/sun/star/xml/dom/SAXDocumentBuilder.hpp>
22 #include <com/sun/star/xml/dom/XSAXDocumentBuilder2.hpp>
23 #include <com/sun/star/xml/xpath/XPathAPI.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/beans/XPropertySetInfo.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <xmloff/xmlmetai.hxx>
28 #include <xmloff/xmlimp.hxx>
29 #include <xmloff/nmspmap.hxx>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmlnmspe.hxx>
33 using namespace com::sun::star
;
34 using namespace ::xmloff::token
;
36 /// builds a DOM tree from SAX events, by forwarding to SAXDocumentBuilder
37 class XMLDocumentBuilderContext
: public SvXMLImportContext
40 ::com::sun::star::uno::Reference
<
41 ::com::sun::star::xml::dom::XSAXDocumentBuilder2
> mxDocBuilder
;
44 XMLDocumentBuilderContext(SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
45 const OUString
& rLName
,
46 const ::com::sun::star::uno::Reference
<
47 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
,
48 const ::com::sun::star::uno::Reference
<
49 ::com::sun::star::xml::dom::XSAXDocumentBuilder2
>& rDocBuilder
);
51 virtual ~XMLDocumentBuilderContext();
53 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
,
54 const OUString
& rLocalName
,
55 const ::com::sun::star::uno::Reference
<
56 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
) SAL_OVERRIDE
;
58 virtual void StartElement( const ::com::sun::star::uno::Reference
<
59 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
) SAL_OVERRIDE
;
61 virtual void Characters( const OUString
& rChars
) SAL_OVERRIDE
;
63 virtual void EndElement() SAL_OVERRIDE
;
66 XMLDocumentBuilderContext::XMLDocumentBuilderContext(SvXMLImport
& rImport
,
67 sal_uInt16 nPrfx
, const OUString
& rLName
,
68 const uno::Reference
<xml::sax::XAttributeList
>&,
69 const uno::Reference
<xml::dom::XSAXDocumentBuilder2
>& rDocBuilder
) :
70 SvXMLImportContext( rImport
, nPrfx
, rLName
),
71 mxDocBuilder(rDocBuilder
)
75 XMLDocumentBuilderContext::~XMLDocumentBuilderContext()
80 XMLDocumentBuilderContext::CreateChildContext( sal_uInt16 nPrefix
,
81 const OUString
& rLocalName
,
82 const uno::Reference
< xml::sax::XAttributeList
>& rAttrs
)
84 return new XMLDocumentBuilderContext(
85 GetImport(), nPrefix
, rLocalName
, rAttrs
, mxDocBuilder
);
88 void XMLDocumentBuilderContext::StartElement(
89 const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
91 mxDocBuilder
->startElement(
92 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()),
96 void XMLDocumentBuilderContext::Characters( const OUString
& rChars
)
98 mxDocBuilder
->characters(rChars
);
101 void XMLDocumentBuilderContext::EndElement()
103 mxDocBuilder
->endElement(
104 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()));
108 lcl_initDocumentProperties(SvXMLImport
& rImport
,
109 uno::Reference
<xml::dom::XSAXDocumentBuilder2
> const& xDocBuilder
,
110 uno::Reference
<document::XDocumentProperties
> const& xDocProps
)
112 uno::Sequence
< uno::Any
> aSeq(1);
113 aSeq
[0] <<= xDocBuilder
->getDocument();
114 uno::Reference
< lang::XInitialization
> const xInit(xDocProps
,
115 uno::UNO_QUERY_THROW
);
117 xInit
->initialize(aSeq
);
118 rImport
.SetStatistics(xDocProps
->getDocumentStatistics());
119 // convert all URLs from relative to absolute
120 xDocProps
->setTemplateURL(rImport
.GetAbsoluteReference(
121 xDocProps
->getTemplateURL()));
122 xDocProps
->setAutoloadURL(rImport
.GetAbsoluteReference(
123 xDocProps
->getAutoloadURL()));
124 SvXMLMetaDocumentContext::setBuildId(
125 xDocProps
->getGenerator(), rImport
.getImportInfo());
126 } catch (const uno::RuntimeException
&) {
128 } catch (const uno::Exception
& e
) {
129 throw lang::WrappedTargetRuntimeException(
131 "SvXMLMetaDocumentContext::initDocumentProperties: "
132 "properties init exception"),
133 rImport
, makeAny(e
));
138 lcl_initGenerator(SvXMLImport
& rImport
,
139 uno::Reference
<xml::dom::XSAXDocumentBuilder2
> const& xDocBuilder
)
141 uno::Reference
< xml::dom::XDocument
> const xDoc(xDocBuilder
->getDocument(),
144 uno::Reference
< xml::xpath::XXPathAPI
> const xPath
= xml::xpath::XPathAPI::create(
145 rImport
.GetComponentContext() );
146 xPath
->registerNS(GetXMLToken(XML_NP_OFFICE
),GetXMLToken(XML_N_OFFICE
));
147 xPath
->registerNS(GetXMLToken(XML_NP_META
), GetXMLToken(XML_N_META
));
149 OUString
const expr( "string(/office:document-meta/office:meta/meta:generator)");
150 uno::Reference
< xml::xpath::XXPathObject
> const xObj(
151 xPath
->eval(xDoc
.get(), expr
), uno::UNO_SET_THROW
);
152 OUString
const value(xObj
->getString());
153 SvXMLMetaDocumentContext::setBuildId(value
, rImport
.getImportInfo());
154 } catch (const uno::RuntimeException
&) {
156 } catch (const uno::Exception
& e
) {
157 throw lang::WrappedTargetRuntimeException(
159 "SvXMLMetaDocumentContext::initGenerator: exception"),
160 rImport
, makeAny(e
));
164 SvXMLMetaDocumentContext::SvXMLMetaDocumentContext(SvXMLImport
& rImport
,
165 sal_uInt16 nPrfx
, const OUString
& rLName
,
166 const uno::Reference
<document::XDocumentProperties
>& xDocProps
) :
167 SvXMLImportContext( rImport
, nPrfx
, rLName
),
168 mxDocProps(xDocProps
),
170 xml::dom::SAXDocumentBuilder::create(
171 comphelper::getProcessComponentContext()))
173 // #i103539#: must always read meta.xml for generator, xDocProps unwanted then
174 // OSL_ENSURE(xDocProps.is(), "SvXMLMetaDocumentContext: no document props");
177 SvXMLMetaDocumentContext::~SvXMLMetaDocumentContext()
181 SvXMLImportContext
*SvXMLMetaDocumentContext::CreateChildContext(
182 sal_uInt16 nPrefix
, const OUString
& rLocalName
,
183 const uno::Reference
<xml::sax::XAttributeList
>& rAttrs
)
185 if ( (XML_NAMESPACE_OFFICE
== nPrefix
) &&
186 IsXMLToken(rLocalName
, XML_META
) )
188 return new XMLDocumentBuilderContext(
189 GetImport(), nPrefix
, rLocalName
, rAttrs
, mxDocBuilder
);
193 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
197 void SvXMLMetaDocumentContext::StartElement(
198 const uno::Reference
< xml::sax::XAttributeList
>& xAttrList
)
200 mxDocBuilder
->startDocument();
201 // hardcode office:document-meta (necessary in case of flat file ODF)
202 mxDocBuilder
->startElement(
203 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(),
204 GetXMLToken(XML_DOCUMENT_META
)), xAttrList
);
208 void SvXMLMetaDocumentContext::EndElement()
210 // hardcode office:document-meta (necessary in case of flat file ODF)
211 mxDocBuilder
->endElement(
212 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(),
213 GetXMLToken(XML_DOCUMENT_META
)));
214 mxDocBuilder
->endDocument();
217 lcl_initDocumentProperties(GetImport(), mxDocBuilder
, mxDocProps
);
221 lcl_initGenerator(GetImport(), mxDocBuilder
);
225 void SvXMLMetaDocumentContext::setBuildId(OUString
const& i_rBuildId
, const uno::Reference
<beans::XPropertySet
>& xImportInfo
)
228 // skip to second product
229 sal_Int32 nBegin
= i_rBuildId
.indexOf( ' ' );
232 // skip to build information
233 nBegin
= i_rBuildId
.indexOf( '/', nBegin
);
236 sal_Int32 nEnd
= i_rBuildId
.indexOf( 'm', nBegin
);
239 OUStringBuffer
sBuffer(
240 i_rBuildId
.copy( nBegin
+1, nEnd
-nBegin
-1 ) );
241 const OUString
sBuildCompare(
243 nBegin
= i_rBuildId
.indexOf( sBuildCompare
, nEnd
);
246 sBuffer
.append( '$' );
247 sBuffer
.append( i_rBuildId
.copy(
248 nBegin
+ sBuildCompare
.getLength() ) );
249 sBuildId
= sBuffer
.makeStringAndClear();
255 if ( sBuildId
.isEmpty() )
257 if ( i_rBuildId
.startsWith("StarOffice 7")
258 || i_rBuildId
.startsWith("StarSuite 7")
259 || i_rBuildId
.startsWith("OpenOffice.org 1"))
261 sBuildId
= "645$8687";
263 else if (i_rBuildId
.startsWith("NeoOffice/2"))
265 sBuildId
= "680$9134"; // fake NeoOffice as OpenOffice.org 2.2 release
270 if (i_rBuildId
.startsWith("LibreOffice/", &rest
) ||
271 i_rBuildId
.startsWith("LibreOfficeDev/", &rest
) ||
272 i_rBuildId
.startsWith("LOdev/", &rest
))
274 OUStringBuffer sNumber
;
275 for (sal_Int32 i
= 0; i
< rest
.getLength(); ++i
)
277 if (isdigit(rest
[i
]))
279 sNumber
.append(rest
[i
]);
281 else if ('.' != rest
[i
])
286 if (!sNumber
.isEmpty())
288 sBuildId
+= (";" + sNumber
.makeStringAndClear());
292 if ( !sBuildId
.isEmpty() ) try
294 if( xImportInfo
.is() )
296 const OUString
aPropName("BuildId");
297 uno::Reference
< beans::XPropertySetInfo
> xSetInfo(
298 xImportInfo
->getPropertySetInfo());
299 if( xSetInfo
.is() && xSetInfo
->hasPropertyByName( aPropName
) )
300 xImportInfo
->setPropertyValue( aPropName
, uno::makeAny( sBuildId
) );
303 catch(const uno::Exception
&)
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */