1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dp_descriptioninfoset.cxx,v $
10 * $Revision: 1.7.34.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
34 #include "dp_descriptioninfoset.hxx"
36 #include "dp_resource.h"
37 #include "sal/config.h"
39 #include "comphelper/sequence.hxx"
40 #include "comphelper/makesequence.hxx"
41 #include "boost/optional.hpp"
42 #include "com/sun/star/beans/Optional.hpp"
43 #include "com/sun/star/lang/XMultiComponentFactory.hpp"
44 #include "com/sun/star/lang/Locale.hpp"
45 #include "com/sun/star/uno/Reference.hxx"
46 #include "com/sun/star/uno/RuntimeException.hpp"
47 #include "com/sun/star/uno/Sequence.hxx"
48 #include "com/sun/star/uno/XComponentContext.hpp"
49 #include "com/sun/star/uno/XInterface.hpp"
50 #include "com/sun/star/xml/dom/DOMException.hpp"
51 #include "com/sun/star/xml/dom/XNode.hpp"
52 #include "com/sun/star/xml/dom/XNodeList.hpp"
53 #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
54 #include "cppuhelper/implbase1.hxx"
55 #include "cppuhelper/weak.hxx"
56 #include "rtl/ustring.h"
57 #include "rtl/ustring.hxx"
58 #include "sal/types.h"
63 namespace css
= ::com::sun::star
;
65 class EmptyNodeList
: public ::cppu::WeakImplHelper1
< css::xml::dom::XNodeList
>
70 virtual ~EmptyNodeList();
72 virtual ::sal_Int32 SAL_CALL
getLength() throw (css::uno::RuntimeException
);
74 virtual css::uno::Reference
< css::xml::dom::XNode
> SAL_CALL
75 item(::sal_Int32 index
) throw (css::uno::RuntimeException
);
78 EmptyNodeList(EmptyNodeList
&); // not defined
79 void operator =(EmptyNodeList
&); // not defined
82 EmptyNodeList::EmptyNodeList() {}
84 EmptyNodeList::~EmptyNodeList() {}
86 ::sal_Int32
EmptyNodeList::getLength() throw (css::uno::RuntimeException
) {
90 css::uno::Reference
< css::xml::dom::XNode
> EmptyNodeList::item(::sal_Int32
)
91 throw (css::uno::RuntimeException
)
93 throw css::uno::RuntimeException(
95 RTL_CONSTASCII_USTRINGPARAM(
96 "bad EmptyNodeList com.sun.star.xml.dom.XNodeList.item call")),
97 static_cast< ::cppu::OWeakObject
* >(this));
100 ::rtl::OUString
getNodeValue(
101 css::uno::Reference
< css::xml::dom::XNode
> const & node
)
103 OSL_ASSERT(node
.is());
105 return node
->getNodeValue();
106 } catch (css::xml::dom::DOMException
& e
) {
107 throw css::uno::RuntimeException(
109 RTL_CONSTASCII_USTRINGPARAM(
110 "com.sun.star.xml.dom.DOMException: ")) +
112 css::uno::Reference
< css::uno::XInterface
>());
120 DescriptionInfoset::DescriptionInfoset(
121 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
122 css::uno::Reference
< css::xml::dom::XNode
> const & element
):
125 css::uno::Reference
< css::lang::XMultiComponentFactory
> manager(
126 context
->getServiceManager(), css::uno::UNO_QUERY_THROW
);
127 if (m_element
.is()) {
128 m_xpath
= css::uno::Reference
< css::xml::xpath::XXPathAPI
>(
129 manager
->createInstanceWithContext(
131 RTL_CONSTASCII_USTRINGPARAM(
132 "com.sun.star.xml.xpath.XPathAPI")),
134 css::uno::UNO_QUERY_THROW
);
136 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")),
137 element
->getNamespaceURI());
139 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")),
141 RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink")));
145 DescriptionInfoset::~DescriptionInfoset() {}
147 ::boost::optional
< ::rtl::OUString
> DescriptionInfoset::getIdentifier() const {
148 return getOptionalValue(
149 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value")));
152 ::rtl::OUString
DescriptionInfoset::getNodeValueFromExpression(::rtl::OUString
const & expression
) const
154 css::uno::Reference
< css::xml::dom::XNode
> n
;
155 if (m_element
.is()) {
157 n
= m_xpath
->selectSingleNode(m_element
, expression
);
158 } catch (css::xml::xpath::XPathException
&) {
162 return n
.is() ? getNodeValue(n
) : ::rtl::OUString();
166 ::rtl::OUString
DescriptionInfoset::getVersion() const
168 return getNodeValueFromExpression( ::rtl::OUString(
169 RTL_CONSTASCII_USTRINGPARAM("desc:version/@value")));
172 css::uno::Sequence
< ::rtl::OUString
> DescriptionInfoset::getSupportedPlaforms() const
174 //When there is no description.xml then we assume that we support all platforms
175 if (! m_element
.is())
177 return comphelper::makeSequence(
178 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
181 //Check if the <platform> element was provided. If not the default is "all" platforms
182 css::uno::Reference
< css::xml::dom::XNode
> nodePlatform(
183 m_xpath
->selectSingleNode(m_element
, ::rtl::OUString(
184 RTL_CONSTASCII_USTRINGPARAM("desc:platform"))));
185 if (!nodePlatform
.is())
187 return comphelper::makeSequence(
188 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
191 //There is a platform element.
192 const ::rtl::OUString value
= getNodeValueFromExpression(::rtl::OUString(
193 RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value")));
194 //parse the string, it can contained multiple strings separated by commas
195 ::std::vector
< ::rtl::OUString
> vec
;
196 sal_Int32 nIndex
= 0;
199 ::rtl::OUString aToken
= value
.getToken( 0, ',', nIndex
);
200 aToken
= aToken
.trim();
201 if (aToken
.getLength())
202 vec
.push_back(aToken
);
207 return comphelper::containerToSequence(vec
);
210 css::uno::Reference
< css::xml::dom::XNodeList
>
211 DescriptionInfoset::getDependencies() const {
212 if (m_element
.is()) {
214 return m_xpath
->selectNodeList(m_element
, ::rtl::OUString(
215 RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*")));
216 } catch (css::xml::xpath::XPathException
&) {
220 return new EmptyNodeList
;
223 css::uno::Sequence
< ::rtl::OUString
>
224 DescriptionInfoset::getUpdateInformationUrls() const {
227 RTL_CONSTASCII_USTRINGPARAM(
228 "desc:update-information/desc:src/@xlink:href")));
231 css::uno::Sequence
< ::rtl::OUString
>
232 DescriptionInfoset::getUpdateDownloadUrls() const
236 RTL_CONSTASCII_USTRINGPARAM(
237 "desc:update-download/desc:src/@xlink:href")));
240 ::rtl::OUString
DescriptionInfoset::getIconURL( sal_Bool bHighContrast
) const
242 css::uno::Sequence
< ::rtl::OUString
> aStrList
= getUrls( ::rtl::OUString(
243 RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href")));
244 css::uno::Sequence
< ::rtl::OUString
> aStrListHC
= getUrls( ::rtl::OUString(
245 RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href")));
247 if ( bHighContrast
&& aStrListHC
.hasElements() && aStrListHC
[0].getLength() )
248 return aStrListHC
[0];
250 if ( aStrList
.hasElements() && aStrList
[0].getLength() )
253 return ::rtl::OUString();
256 ::boost::optional
< ::rtl::OUString
> DescriptionInfoset::getLocalizedUpdateWebsiteURL()
259 bool bParentExists
= false;
260 const ::rtl::OUString
sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
261 "/desc:description/desc:update-website")), &bParentExists
));
263 if (sURL
.getLength() > 0)
264 return ::boost::optional
< ::rtl::OUString
>(sURL
);
266 return bParentExists
? ::boost::optional
< ::rtl::OUString
>(::rtl::OUString()) :
267 ::boost::optional
< ::rtl::OUString
>();
270 css::uno::Reference
< css::xml::xpath::XXPathAPI
> DescriptionInfoset::getXpath()
276 ::boost::optional
< ::rtl::OUString
> DescriptionInfoset::getOptionalValue(
277 ::rtl::OUString
const & expression
) const
279 css::uno::Reference
< css::xml::dom::XNode
> n
;
280 if (m_element
.is()) {
282 n
= m_xpath
->selectSingleNode(m_element
, expression
);
283 } catch (css::xml::xpath::XPathException
&) {
288 ? ::boost::optional
< ::rtl::OUString
>(getNodeValue(n
))
289 : ::boost::optional
< ::rtl::OUString
>();
292 css::uno::Sequence
< ::rtl::OUString
> DescriptionInfoset::getUrls(
293 ::rtl::OUString
const & expression
) const
295 css::uno::Reference
< css::xml::dom::XNodeList
> ns
;
296 if (m_element
.is()) {
298 ns
= m_xpath
->selectNodeList(m_element
, expression
);
299 } catch (css::xml::xpath::XPathException
&) {
303 css::uno::Sequence
< ::rtl::OUString
> urls(ns
.is() ? ns
->getLength() : 0);
304 for (::sal_Int32 i
= 0; i
< urls
.getLength(); ++i
) {
305 urls
[i
] = getNodeValue(ns
->item(i
));
310 ::std::pair
< ::rtl::OUString
, ::rtl::OUString
> DescriptionInfoset::getLocalizedPublisherNameAndURL() const
312 css::uno::Reference
< css::xml::dom::XNode
> node
=
313 getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher")));
315 ::rtl::OUString sPublisherName
;
316 ::rtl::OUString sURL
;
319 const ::rtl::OUString
exp1(RTL_CONSTASCII_USTRINGPARAM("text()"));
320 css::uno::Reference
< css::xml::dom::XNode
> xPathName
;
322 xPathName
= m_xpath
->selectSingleNode(node
, exp1
);
323 } catch (css::xml::xpath::XPathException
&) {
326 OSL_ASSERT(xPathName
.is());
328 sPublisherName
= xPathName
->getNodeValue();
330 const ::rtl::OUString
exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
331 css::uno::Reference
< css::xml::dom::XNode
> xURL
;
333 xURL
= m_xpath
->selectSingleNode(node
, exp2
);
334 } catch (css::xml::xpath::XPathException
&) {
337 OSL_ASSERT(xURL
.is());
339 sURL
= xURL
->getNodeValue();
341 return ::std::make_pair(sPublisherName
, sURL
);
344 ::rtl::OUString
DescriptionInfoset::getLocalizedReleaseNotesURL() const
346 return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
347 "/desc:description/desc:release-notes")), NULL
);
350 ::rtl::OUString
DescriptionInfoset::getLocalizedDisplayName() const
352 css::uno::Reference
< css::xml::dom::XNode
> node
=
353 getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name")));
356 const ::rtl::OUString
exp(RTL_CONSTASCII_USTRINGPARAM("text()"));
357 css::uno::Reference
< css::xml::dom::XNode
> xtext
;
359 xtext
= m_xpath
->selectSingleNode(node
, exp
);
360 } catch (css::xml::xpath::XPathException
&) {
364 return xtext
->getNodeValue();
366 return ::rtl::OUString();
369 ::rtl::OUString
DescriptionInfoset::getLocalizedLicenseURL() const
371 return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
372 "/desc:description/desc:registration/desc:simple-license")), NULL
);
376 ::rtl::OUString
DescriptionInfoset::getLocalizedDescriptionURL() const
378 return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
379 "/desc:description/desc:extension-description")), NULL
);
382 css::uno::Reference
< css::xml::dom::XNode
>
383 DescriptionInfoset::getLocalizedChild( const ::rtl::OUString
& sParent
) const
385 if ( ! m_element
.is() || !sParent
.getLength())
386 return css::uno::Reference
< css::xml::dom::XNode
> ();
388 css::uno::Reference
< css::xml::dom::XNode
> xParent
;
390 xParent
= m_xpath
->selectSingleNode(m_element
, sParent
);
391 } catch (css::xml::xpath::XPathException
&) {
394 css::uno::Reference
<css::xml::dom::XNode
> nodeMatch
;
397 const ::rtl::OUString sLocale
= getOfficeLocaleString();
398 nodeMatch
= matchFullLocale(xParent
, sLocale
);
400 //office: en-DE, en, en-DE-altmark
401 if (! nodeMatch
.is())
403 const css::lang::Locale officeLocale
= getOfficeLocale();
404 nodeMatch
= matchCountryAndLanguage(xParent
, officeLocale
);
405 if ( ! nodeMatch
.is())
407 nodeMatch
= matchLanguage(xParent
, officeLocale
);
408 if (! nodeMatch
.is())
409 nodeMatch
= getChildWithDefaultLocale(xParent
);
417 css::uno::Reference
<css::xml::dom::XNode
>
418 DescriptionInfoset::matchFullLocale(css::uno::Reference
< css::xml::dom::XNode
>
419 const & xParent
, ::rtl::OUString
const & sLocale
) const
421 OSL_ASSERT(xParent
.is());
422 const ::rtl::OUString
exp1(
423 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
425 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
427 return m_xpath
->selectSingleNode(xParent
, exp1
);
428 } catch (css::xml::xpath::XPathException
&) {
434 css::uno::Reference
<css::xml::dom::XNode
>
435 DescriptionInfoset::matchCountryAndLanguage(
436 css::uno::Reference
< css::xml::dom::XNode
> const & xParent
, css::lang::Locale
const & officeLocale
) const
438 OSL_ASSERT(xParent
.is());
439 css::uno::Reference
<css::xml::dom::XNode
> nodeMatch
;
441 if (officeLocale
.Country
.getLength())
443 const ::rtl::OUString
sLangCountry(officeLocale
.Language
+
444 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) +
445 officeLocale
.Country
);
446 //first try exact match for lang-country
447 const ::rtl::OUString
exp1(
448 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
450 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
452 nodeMatch
= m_xpath
->selectSingleNode(xParent
, exp1
);
453 } catch (css::xml::xpath::XPathException
&) {
457 //try to match in strings that also have a variant, for example en-US matches in
461 const ::rtl::OUString
exp2(
462 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
464 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
466 nodeMatch
= m_xpath
->selectSingleNode(xParent
, exp2
);
467 } catch (css::xml::xpath::XPathException
&) {
477 css::uno::Reference
<css::xml::dom::XNode
>
478 DescriptionInfoset::matchLanguage(
479 css::uno::Reference
< css::xml::dom::XNode
> const & xParent
, css::lang::Locale
const & officeLocale
) const
481 OSL_ASSERT(xParent
.is());
482 css::uno::Reference
<css::xml::dom::XNode
> nodeMatch
;
484 //first try exact match for lang
485 const ::rtl::OUString
exp1(
486 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
487 + officeLocale
.Language
488 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
490 nodeMatch
= m_xpath
->selectSingleNode(xParent
, exp1
);
491 } catch (css::xml::xpath::XPathException
&) {
495 //try to match in strings that also have a country and/orvariant, for example en matches in
496 //en-US-montana, en-US, en-montana
499 const ::rtl::OUString
exp2(
500 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
501 + officeLocale
.Language
502 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
504 nodeMatch
= m_xpath
->selectSingleNode(xParent
, exp2
);
505 } catch (css::xml::xpath::XPathException
&) {
512 css::uno::Reference
<css::xml::dom::XNode
>
513 DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference
< css::xml::dom::XNode
>
514 const & xParent
) const
516 OSL_ASSERT(xParent
.is());
517 if (xParent
->getNodeName().equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple-license"))))
519 css::uno::Reference
<css::xml::dom::XNode
> nodeDefault
;
521 nodeDefault
= m_xpath
->selectSingleNode(xParent
, ::rtl::OUString(
522 RTL_CONSTASCII_USTRINGPARAM("@default-license-id")));
523 } catch (css::xml::xpath::XPathException
&) {
526 if (nodeDefault
.is())
529 const ::rtl::OUString
exp1(
530 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \""))
531 + nodeDefault
->getNodeValue()
532 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
534 return m_xpath
->selectSingleNode(xParent
, exp1
);
535 } catch (css::xml::xpath::XPathException
&) {
541 const ::rtl::OUString
exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]"));
543 return m_xpath
->selectSingleNode(xParent
, exp2
);
544 } catch (css::xml::xpath::XPathException
&) {
550 ::rtl::OUString
DescriptionInfoset::getLocalizedHREFAttrFromChild(
551 ::rtl::OUString
const & sXPathParent
, bool * out_bParentExists
)
554 css::uno::Reference
< css::xml::dom::XNode
> node
=
555 getLocalizedChild(sXPathParent
);
557 ::rtl::OUString sURL
;
560 if (out_bParentExists
)
561 *out_bParentExists
= true;
562 const ::rtl::OUString
exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
563 css::uno::Reference
< css::xml::dom::XNode
> xURL
;
565 xURL
= m_xpath
->selectSingleNode(node
, exp
);
566 } catch (css::xml::xpath::XPathException
&) {
569 OSL_ASSERT(xURL
.is());
571 sURL
= xURL
->getNodeValue();
575 if (out_bParentExists
)
576 *out_bParentExists
= false;