Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "dp_descriptioninfoset.hxx"
31 : :
32 : : #include "dp_resource.h"
33 : : #include "sal/config.h"
34 : :
35 : : #include "comphelper/sequence.hxx"
36 : : #include "comphelper/makesequence.hxx"
37 : : #include "comphelper/processfactory.hxx"
38 : : #include "boost/optional.hpp"
39 : : #include "com/sun/star/beans/Optional.hpp"
40 : : #include "com/sun/star/lang/XMultiComponentFactory.hpp"
41 : : #include "com/sun/star/lang/Locale.hpp"
42 : : #include "com/sun/star/uno/Reference.hxx"
43 : : #include "com/sun/star/uno/RuntimeException.hpp"
44 : : #include "com/sun/star/uno/Sequence.hxx"
45 : : #include "com/sun/star/uno/XComponentContext.hpp"
46 : : #include "com/sun/star/uno/XInterface.hpp"
47 : : #include "com/sun/star/xml/dom/DOMException.hpp"
48 : : #include "com/sun/star/xml/dom/XNode.hpp"
49 : : #include "com/sun/star/xml/dom/XNodeList.hpp"
50 : : #include "com/sun/star/xml/dom/XDocumentBuilder.hpp"
51 : : #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
52 : : #include "com/sun/star/ucb/InteractiveIOException.hpp"
53 : : #include "cppuhelper/implbase1.hxx"
54 : : #include "cppuhelper/implbase2.hxx"
55 : : #include "cppuhelper/weak.hxx"
56 : : #include "cppuhelper/exc_hlp.hxx"
57 : : #include "rtl/ustring.h"
58 : : #include "rtl/ustring.hxx"
59 : : #include "sal/types.h"
60 : : #include "ucbhelper/content.hxx"
61 : :
62 : : namespace {
63 : :
64 : : namespace css = ::com::sun::star;
65 : : using css::uno::Reference;
66 : : using ::rtl::OUString;
67 : :
68 : : class EmptyNodeList: public ::cppu::WeakImplHelper1< css::xml::dom::XNodeList >
69 : : {
70 : : public:
71 : : EmptyNodeList();
72 : :
73 : : virtual ~EmptyNodeList();
74 : :
75 : : virtual ::sal_Int32 SAL_CALL getLength() throw (css::uno::RuntimeException);
76 : :
77 : : virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL
78 : : item(::sal_Int32 index) throw (css::uno::RuntimeException);
79 : :
80 : : private:
81 : : EmptyNodeList(EmptyNodeList &); // not defined
82 : : void operator =(EmptyNodeList &); // not defined
83 : : };
84 : :
85 : 0 : EmptyNodeList::EmptyNodeList() {}
86 : :
87 [ # # ]: 0 : EmptyNodeList::~EmptyNodeList() {}
88 : :
89 : 0 : ::sal_Int32 EmptyNodeList::getLength() throw (css::uno::RuntimeException) {
90 : 0 : return 0;
91 : : }
92 : :
93 : 0 : css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32)
94 : : throw (css::uno::RuntimeException)
95 : : {
96 : : throw css::uno::RuntimeException(
97 : : ::rtl::OUString(
98 : : RTL_CONSTASCII_USTRINGPARAM(
99 : : "bad EmptyNodeList com.sun.star.xml.dom.XNodeList.item call")),
100 [ # # ][ # # ]: 0 : static_cast< ::cppu::OWeakObject * >(this));
[ # # ]
101 : : }
102 : :
103 : 2356 : ::rtl::OUString getNodeValue(
104 : : css::uno::Reference< css::xml::dom::XNode > const & node)
105 : : {
106 : : OSL_ASSERT(node.is());
107 : : try {
108 [ + - ][ + - ]: 2356 : return node->getNodeValue();
109 [ # # ]: 0 : } catch (const css::xml::dom::DOMException & e) {
110 : : throw css::uno::RuntimeException(
111 : : (::rtl::OUString(
112 : : RTL_CONSTASCII_USTRINGPARAM(
113 : : "com.sun.star.xml.dom.DOMException: ")) +
114 : : e.Message),
115 [ # # # # ]: 0 : css::uno::Reference< css::uno::XInterface >());
116 : : }
117 : : }
118 : :
119 : : /**The class uses the UCB to access the description.xml file in an
120 : : extension. The UCB must have been initialized already. It also
121 : : requires that the extension has already be unzipped to a particular
122 : : location.
123 : : */
124 : : class ExtensionDescription
125 : : {
126 : : public:
127 : : /**throws an exception if the description.xml is not
128 : : available, cannot be read, does not contain the expected data,
129 : : or any other error occurred. Therefore it shoult only be used with
130 : : new extensions.
131 : :
132 : : Throws com::sun::star::uno::RuntimeException,
133 : : com::sun::star::deployment::DeploymentException,
134 : : dp_registry::backend::bundle::NoDescriptionException.
135 : : */
136 : : ExtensionDescription(
137 : : const css::uno::Reference<css::uno::XComponentContext>& xContext,
138 : : const ::rtl::OUString& installDir,
139 : : const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv);
140 : :
141 : : ~ExtensionDescription();
142 : :
143 : 8184 : css::uno::Reference<css::xml::dom::XNode> getRootElement() const
144 : : {
145 : 8184 : return m_xRoot;
146 : : }
147 : :
148 : : ::rtl::OUString getExtensionRootUrl() const
149 : : {
150 : : return m_sExtensionRootUrl;
151 : : }
152 : :
153 : :
154 : : private:
155 : : css::uno::Reference<css::xml::dom::XNode> m_xRoot;
156 : : ::rtl::OUString m_sExtensionRootUrl;
157 : : };
158 : :
159 : : class NoDescriptionException
160 : : {
161 : : };
162 : :
163 : : class FileDoesNotExistFilter
164 : : : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment,
165 : : css::task::XInteractionHandler >
166 : :
167 : : {
168 : : bool m_bExist;
169 : : css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv;
170 : :
171 : : public:
172 : : virtual ~FileDoesNotExistFilter();
173 : : FileDoesNotExistFilter(
174 : : const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv);
175 : :
176 : : bool exist();
177 : : // XCommandEnvironment
178 : : virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL
179 : : getInteractionHandler() throw (css::uno::RuntimeException);
180 : : virtual css::uno::Reference<css::ucb::XProgressHandler >
181 : : SAL_CALL getProgressHandler() throw (css::uno::RuntimeException);
182 : :
183 : : // XInteractionHandler
184 : : virtual void SAL_CALL handle(
185 : : css::uno::Reference<css::task::XInteractionRequest > const & xRequest )
186 : : throw (css::uno::RuntimeException);
187 : : };
188 : :
189 : 8226 : ExtensionDescription::ExtensionDescription(
190 : : const Reference<css::uno::XComponentContext>& xContext,
191 : : const OUString& installDir,
192 : 8268 : const Reference< css::ucb::XCommandEnvironment >& xCmdEnv)
193 : : {
194 : : try {
195 : 8226 : m_sExtensionRootUrl = installDir;
196 : : //may throw ::com::sun::star::ucb::ContentCreationException
197 : : //If there is no description.xml then ucb will start an interaction which
198 : : //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv
199 : : //and filter the respective exception out.
200 [ + - ]: 8226 : OUString sDescriptionUri(installDir + OUSTR("/description.xml"));
201 : : Reference<css::ucb::XCommandEnvironment> xFilter =
202 : : static_cast<css::ucb::XCommandEnvironment*>(
203 [ + - ][ + - ]: 8226 : new FileDoesNotExistFilter(xCmdEnv));
[ + - ]
204 [ + - ]: 8226 : ::ucbhelper::Content descContent(sDescriptionUri, xFilter);
205 : :
206 : : //throws an com::sun::star::uno::Exception if the file is not available
207 : 8226 : Reference<css::io::XInputStream> xIn;
208 : : try
209 : : { //throws com.sun.star.ucb.InteractiveIOException
210 [ + - ][ + + ]: 8226 : xIn = descContent.openStream();
211 : : }
212 [ - + ]: 84 : catch ( const css::uno::Exception& )
213 : : {
214 [ + - ][ + - ]: 42 : if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist())
[ - + ]
215 : 42 : throw NoDescriptionException();
216 : 0 : throw;
217 : : }
218 [ - + ]: 8184 : if (!xIn.is())
219 : : {
220 : : throw css::uno::Exception(
221 : : OUSTR("Could not get XInputStream for description.xml of extension ") +
222 [ # # ][ # # ]: 0 : sDescriptionUri, 0);
[ # # ]
223 : : }
224 : :
225 : : //get root node of description.xml
226 : : Reference<css::xml::dom::XDocumentBuilder> xDocBuilder(
227 [ + - ][ + - ]: 16368 : xContext->getServiceManager()->createInstanceWithContext(
[ + - ]
228 : : OUSTR("com.sun.star.xml.dom.DocumentBuilder"),
229 [ + - ][ + - ]: 8184 : xContext ), css::uno::UNO_QUERY);
[ + - ]
230 [ - + ]: 8184 : if (!xDocBuilder.is())
231 [ # # ][ # # ]: 0 : throw css::uno::Exception(OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0);
[ # # ]
232 : :
233 [ + - ][ + - ]: 8184 : if (xDocBuilder->isNamespaceAware() == sal_False)
[ - + ]
234 : : {
235 : : throw css::uno::Exception(
236 [ # # ][ # # ]: 0 : OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0);
[ # # ]
237 : : }
238 : :
239 [ + - ][ + - ]: 8184 : Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn);
240 [ - + ]: 8184 : if (!xDoc.is())
241 : : {
242 [ # # ][ # # ]: 0 : throw css::uno::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0);
[ # # ]
243 : : }
244 : :
245 : : //check for proper root element and namespace
246 [ + - ][ + - ]: 8184 : Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement();
247 [ - + ]: 8184 : if (!xRoot.is())
248 : : {
249 : : throw css::uno::Exception(
250 [ # # ][ # # ]: 0 : sDescriptionUri + OUSTR(" contains no root element."), 0);
[ # # ]
251 : : }
252 : :
253 [ + - ][ + - ]: 8184 : if ( ! xRoot->getTagName().equals(OUSTR("description")))
[ + - ][ - + ]
254 : : {
255 : : throw css::uno::Exception(
256 [ # # ][ # # ]: 0 : sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0);
[ # # ]
257 : : }
258 : :
259 : : m_xRoot = Reference<css::xml::dom::XNode>(
260 [ + - ][ + - ]: 8184 : xRoot, css::uno::UNO_QUERY_THROW);
261 [ + - ][ + - ]: 8184 : OUString nsDescription = xRoot->getNamespaceURI();
262 : :
263 : : //check if this namespace is supported
264 [ + - ][ - + ]: 8184 : if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006")))
265 : : {
266 [ # # ][ # # ]: 0 : throw css::uno::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0);
[ # # ]
267 [ + - ]: 8226 : }
268 : 0 : } catch (const css::uno::RuntimeException &) {
269 : 0 : throw;
270 : 0 : } catch (const css::deployment::DeploymentException &) {
271 : 0 : throw;
272 [ + - - - ]: 42 : } catch (const css::uno::Exception & e) {
273 [ # # ]: 0 : css::uno::Any a(cppu::getCaughtException());
274 : : throw css::deployment::DeploymentException(
275 [ # # ]: 0 : e.Message, Reference< css::uno::XInterface >(), a);
276 : : }
277 : 8184 : }
278 : :
279 : 8184 : ExtensionDescription::~ExtensionDescription()
280 : : {
281 : 8184 : }
282 : :
283 : : //======================================================================
284 : 8226 : FileDoesNotExistFilter::FileDoesNotExistFilter(
285 : : const Reference< css::ucb::XCommandEnvironment >& xCmdEnv):
286 : 8226 : m_bExist(true), m_xCommandEnv(xCmdEnv)
287 : 8226 : {}
288 : :
289 : 8226 : FileDoesNotExistFilter::~FileDoesNotExistFilter()
290 : : {
291 [ - + ]: 16452 : };
292 : :
293 : 42 : bool FileDoesNotExistFilter::exist()
294 : : {
295 : 42 : return m_bExist;
296 : : }
297 : : // XCommandEnvironment
298 : : Reference<css::task::XInteractionHandler >
299 : 42 : FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException)
300 : : {
301 : 42 : return static_cast<css::task::XInteractionHandler*>(this);
302 : : }
303 : :
304 : : Reference<css::ucb::XProgressHandler >
305 : 0 : FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException)
306 : : {
307 : 0 : return m_xCommandEnv.is()
308 : 0 : ? m_xCommandEnv->getProgressHandler()
309 [ # # ]: 0 : : Reference<css::ucb::XProgressHandler>();
310 : : }
311 : :
312 : : // XInteractionHandler
313 : : //If the interaction was caused by a non-existing file which is specified in the ctor
314 : : //of FileDoesNotExistFilter, then we do nothing
315 : 42 : void FileDoesNotExistFilter::handle(
316 : : Reference<css::task::XInteractionRequest > const & xRequest )
317 : : throw (css::uno::RuntimeException)
318 : : {
319 [ + - ][ + - ]: 42 : css::uno::Any request( xRequest->getRequest() );
320 : :
321 [ + - ]: 42 : css::ucb::InteractiveIOException ioexc;
322 [ + - ][ + - ]: 42 : if ((request>>= ioexc)
[ - + ][ # # ]
[ + - ]
323 : : && (ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING
324 : : || ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING_PATH))
325 : : {
326 : 42 : m_bExist = false;
327 : 42 : return;
328 : : }
329 : 0 : Reference<css::task::XInteractionHandler> xInteraction;
330 [ # # ]: 0 : if (m_xCommandEnv.is()) {
331 [ # # ][ # # ]: 0 : xInteraction = m_xCommandEnv->getInteractionHandler();
[ # # ]
332 : : }
333 [ # # ]: 0 : if (xInteraction.is()) {
334 [ # # ][ # # ]: 0 : xInteraction->handle(xRequest);
335 [ + - ][ + - ]: 42 : }
[ - + ]
336 : : }
337 : :
338 : : }
339 : :
340 : : namespace dp_misc {
341 : :
342 : 8226 : DescriptionInfoset getDescriptionInfoset(OUString const & sExtensionFolderURL)
343 : : {
344 : 8226 : Reference< css::xml::dom::XNode > root;
345 : : Reference<css::uno::XComponentContext> context =
346 [ + - ][ + - ]: 8226 : comphelper_getProcessComponentContext();
347 : : OSL_ASSERT(context.is());
348 : : try {
349 : : root =
350 : : ExtensionDescription(
351 : : context, sExtensionFolderURL,
352 : : Reference< css::ucb::XCommandEnvironment >()).
353 [ + + ][ + - ]: 8226 : getRootElement();
[ + - ][ + - ]
354 : 42 : } catch (const NoDescriptionException &) {
355 [ - + - ]: 42 : } catch (const css::deployment::DeploymentException & e) {
356 : : throw css::uno::RuntimeException(
357 : : (OUString(
358 : : RTL_CONSTASCII_USTRINGPARAM(
359 : : "com.sun.star.deployment.DeploymentException: ")) +
360 [ # # # # : 0 : e.Message), 0);
# # ]
361 : : }
362 [ + - ]: 8226 : return DescriptionInfoset(context, root);
363 : : }
364 : :
365 : 8226 : DescriptionInfoset::DescriptionInfoset(
366 : : css::uno::Reference< css::uno::XComponentContext > const & context,
367 : : css::uno::Reference< css::xml::dom::XNode > const & element):
368 : 8226 : m_element(element)
369 : : {
370 : : css::uno::Reference< css::lang::XMultiComponentFactory > manager(
371 [ + - ][ + - ]: 8226 : context->getServiceManager(), css::uno::UNO_QUERY_THROW);
[ + - ]
372 [ + + ]: 8226 : if (m_element.is()) {
373 : : m_xpath = css::uno::Reference< css::xml::xpath::XXPathAPI >(
374 [ + - ]: 8184 : manager->createInstanceWithContext(
375 : : ::rtl::OUString(
376 : : RTL_CONSTASCII_USTRINGPARAM(
377 : : "com.sun.star.xml.xpath.XPathAPI")),
378 : 8184 : context),
379 [ + - ][ + - ]: 8184 : css::uno::UNO_QUERY_THROW);
[ + - ][ + - ]
380 [ + - ]: 8184 : m_xpath->registerNS(
381 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")),
382 [ + - ][ + - ]: 8184 : element->getNamespaceURI());
[ + - ][ + - ]
383 [ + - ]: 8184 : m_xpath->registerNS(
384 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")),
385 : : ::rtl::OUString(
386 [ + - ][ + - ]: 8184 : RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink")));
[ + - ]
387 : 8226 : }
388 : 8226 : }
389 : :
390 : 8226 : DescriptionInfoset::~DescriptionInfoset() {}
391 : :
392 : 1510 : ::boost::optional< ::rtl::OUString > DescriptionInfoset::getIdentifier() const {
393 : : return getOptionalValue(
394 [ + - ]: 1510 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value")));
395 : : }
396 : :
397 : 876 : ::rtl::OUString DescriptionInfoset::getNodeValueFromExpression(::rtl::OUString const & expression) const
398 : : {
399 : 876 : css::uno::Reference< css::xml::dom::XNode > n;
400 [ + + ]: 876 : if (m_element.is()) {
401 : : try {
402 [ + - ][ + - ]: 868 : n = m_xpath->selectSingleNode(m_element, expression);
[ + - ][ # # ]
403 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
404 : : // ignore
405 : : }
406 : : }
407 [ + + ][ + - ]: 876 : return n.is() ? getNodeValue(n) : ::rtl::OUString();
408 : : }
409 : :
410 : :
411 : 504 : ::rtl::OUString DescriptionInfoset::getVersion() const
412 : : {
413 : : return getNodeValueFromExpression( ::rtl::OUString(
414 [ + - ]: 504 : RTL_CONSTASCII_USTRINGPARAM("desc:version/@value")));
415 : : }
416 : :
417 : 496 : css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getSupportedPlaforms() const
418 : : {
419 : : //When there is no description.xml then we assume that we support all platforms
420 [ - + ]: 496 : if (! m_element.is())
421 : : {
422 : : return comphelper::makeSequence(
423 [ # # ][ # # ]: 0 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
424 : : }
425 : :
426 : : //Check if the <platform> element was provided. If not the default is "all" platforms
427 : : css::uno::Reference< css::xml::dom::XNode > nodePlatform(
428 [ + - ]: 496 : m_xpath->selectSingleNode(m_element, ::rtl::OUString(
429 [ + - ][ + - ]: 496 : RTL_CONSTASCII_USTRINGPARAM("desc:platform"))));
430 [ + + ]: 496 : if (!nodePlatform.is())
431 : : {
432 : : return comphelper::makeSequence(
433 [ + - ][ + - ]: 124 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
434 : : }
435 : :
436 : : //There is a platform element.
437 : : const ::rtl::OUString value = getNodeValueFromExpression(::rtl::OUString(
438 [ + - ][ + - ]: 372 : RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value")));
439 : : //parse the string, it can contained multiple strings separated by commas
440 [ + - ]: 372 : ::std::vector< ::rtl::OUString> vec;
441 : 372 : sal_Int32 nIndex = 0;
442 [ - + ]: 372 : do
443 : : {
444 : 372 : ::rtl::OUString aToken = value.getToken( 0, ',', nIndex );
445 : 372 : aToken = aToken.trim();
446 [ + - ]: 372 : if (!aToken.isEmpty())
447 [ + - ]: 372 : vec.push_back(aToken);
448 : :
449 : : }
450 : : while (nIndex >= 0);
451 : :
452 [ + - ]: 496 : return comphelper::containerToSequence(vec);
453 : : }
454 : :
455 : : css::uno::Reference< css::xml::dom::XNodeList >
456 : 496 : DescriptionInfoset::getDependencies() const {
457 [ + - ]: 496 : if (m_element.is()) {
458 : : try {
459 [ + - ]: 496 : return m_xpath->selectNodeList(m_element, ::rtl::OUString(
460 [ + - ][ + - ]: 496 : RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*")));
[ # # ]
461 : 0 : } catch (const css::xml::xpath::XPathException &) {
462 : : // ignore
463 : : }
464 : : }
465 [ # # ][ # # ]: 496 : return new EmptyNodeList;
466 : : }
467 : :
468 : : css::uno::Sequence< ::rtl::OUString >
469 : 0 : DescriptionInfoset::getUpdateInformationUrls() const {
470 : : return getUrls(
471 : : ::rtl::OUString(
472 : : RTL_CONSTASCII_USTRINGPARAM(
473 [ # # ]: 0 : "desc:update-information/desc:src/@xlink:href")));
474 : : }
475 : :
476 : : css::uno::Sequence< ::rtl::OUString >
477 : 0 : DescriptionInfoset::getUpdateDownloadUrls() const
478 : : {
479 : : return getUrls(
480 : : ::rtl::OUString(
481 : : RTL_CONSTASCII_USTRINGPARAM(
482 [ # # ]: 0 : "desc:update-download/desc:src/@xlink:href")));
483 : : }
484 : :
485 : 0 : ::rtl::OUString DescriptionInfoset::getIconURL( sal_Bool bHighContrast ) const
486 : : {
487 : : css::uno::Sequence< ::rtl::OUString > aStrList = getUrls( ::rtl::OUString(
488 [ # # ][ # # ]: 0 : RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href")));
489 : : css::uno::Sequence< ::rtl::OUString > aStrListHC = getUrls( ::rtl::OUString(
490 [ # # ][ # # ]: 0 : RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href")));
491 : :
492 [ # # ][ # # ]: 0 : if ( bHighContrast && aStrListHC.hasElements() && !aStrListHC[0].isEmpty() )
[ # # ][ # # ]
[ # # ]
493 [ # # ]: 0 : return aStrListHC[0];
494 : :
495 [ # # ][ # # ]: 0 : if ( aStrList.hasElements() && !aStrList[0].isEmpty() )
[ # # ][ # # ]
496 [ # # ]: 0 : return aStrList[0];
497 : :
498 [ # # ][ # # ]: 0 : return ::rtl::OUString();
499 : : }
500 : :
501 : 0 : ::boost::optional< ::rtl::OUString > DescriptionInfoset::getLocalizedUpdateWebsiteURL()
502 : : const
503 : : {
504 : 0 : bool bParentExists = false;
505 : : const ::rtl::OUString sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
506 [ # # ][ # # ]: 0 : "/desc:description/desc:update-website")), &bParentExists ));
507 : :
508 [ # # ]: 0 : if (!sURL.isEmpty())
509 [ # # ]: 0 : return ::boost::optional< ::rtl::OUString >(sURL);
510 : : else
511 : : return bParentExists ? ::boost::optional< ::rtl::OUString >(::rtl::OUString()) :
512 [ # # ][ # # ]: 0 : ::boost::optional< ::rtl::OUString >();
[ # # ][ # # ]
[ # # ]
513 : : }
514 : :
515 : 1510 : ::boost::optional< ::rtl::OUString > DescriptionInfoset::getOptionalValue(
516 : : ::rtl::OUString const & expression) const
517 : : {
518 : 1510 : css::uno::Reference< css::xml::dom::XNode > n;
519 [ + + ]: 1510 : if (m_element.is()) {
520 : : try {
521 [ + - ][ + - ]: 1488 : n = m_xpath->selectSingleNode(m_element, expression);
[ + - ][ # # ]
522 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
523 : : // ignore
524 : : }
525 : : }
526 : 1510 : return n.is()
527 : : ? ::boost::optional< ::rtl::OUString >(getNodeValue(n))
528 [ + - ][ + - ]: 1510 : : ::boost::optional< ::rtl::OUString >();
[ + - ][ + + ]
[ # # ][ + + ]
529 : : }
530 : :
531 : 0 : css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getUrls(
532 : : ::rtl::OUString const & expression) const
533 : : {
534 : 0 : css::uno::Reference< css::xml::dom::XNodeList > ns;
535 [ # # ]: 0 : if (m_element.is()) {
536 : : try {
537 [ # # ][ # # ]: 0 : ns = m_xpath->selectNodeList(m_element, expression);
[ # # ][ # # ]
538 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
539 : : // ignore
540 : : }
541 : : }
542 [ # # ][ # # ]: 0 : css::uno::Sequence< ::rtl::OUString > urls(ns.is() ? ns->getLength() : 0);
[ # # ][ # # ]
543 [ # # ]: 0 : for (::sal_Int32 i = 0; i < urls.getLength(); ++i) {
544 [ # # ][ # # ]: 0 : urls[i] = getNodeValue(ns->item(i));
[ # # ][ # # ]
545 : : }
546 : 0 : return urls;
547 : : }
548 : :
549 : 0 : ::std::pair< ::rtl::OUString, ::rtl::OUString > DescriptionInfoset::getLocalizedPublisherNameAndURL() const
550 : : {
551 : : css::uno::Reference< css::xml::dom::XNode > node =
552 [ # # ][ # # ]: 0 : getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher")));
553 : :
554 : 0 : ::rtl::OUString sPublisherName;
555 : 0 : ::rtl::OUString sURL;
556 [ # # ]: 0 : if (node.is())
557 : : {
558 [ # # ]: 0 : const ::rtl::OUString exp1(RTL_CONSTASCII_USTRINGPARAM("text()"));
559 : 0 : css::uno::Reference< css::xml::dom::XNode > xPathName;
560 : : try {
561 [ # # ][ # # ]: 0 : xPathName = m_xpath->selectSingleNode(node, exp1);
[ # # ][ # # ]
562 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
563 : : // ignore
564 : : }
565 : : OSL_ASSERT(xPathName.is());
566 [ # # ]: 0 : if (xPathName.is())
567 [ # # ][ # # ]: 0 : sPublisherName = xPathName->getNodeValue();
568 : :
569 [ # # ]: 0 : const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
570 : 0 : css::uno::Reference< css::xml::dom::XNode > xURL;
571 : : try {
572 [ # # ][ # # ]: 0 : xURL = m_xpath->selectSingleNode(node, exp2);
[ # # ][ # # ]
573 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
574 : : // ignore
575 : : }
576 : : OSL_ASSERT(xURL.is());
577 [ # # ]: 0 : if (xURL.is())
578 [ # # ][ # # ]: 0 : sURL = xURL->getNodeValue();
579 : : }
580 : 0 : return ::std::make_pair(sPublisherName, sURL);
581 : : }
582 : :
583 : 0 : ::rtl::OUString DescriptionInfoset::getLocalizedReleaseNotesURL() const
584 : : {
585 : : return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
586 [ # # ]: 0 : "/desc:description/desc:release-notes")), NULL);
587 : : }
588 : :
589 : 4718 : ::rtl::OUString DescriptionInfoset::getLocalizedDisplayName() const
590 : : {
591 : : css::uno::Reference< css::xml::dom::XNode > node =
592 [ + - ][ + - ]: 4718 : getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name")));
593 [ + + ]: 4718 : if (node.is())
594 : : {
595 [ + - ]: 4712 : const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("text()"));
596 : 4712 : css::uno::Reference< css::xml::dom::XNode > xtext;
597 : : try {
598 [ + - ][ + - ]: 4712 : xtext = m_xpath->selectSingleNode(node, exp);
[ # # ][ + - ]
599 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
600 : : // ignore
601 : : }
602 [ + - ]: 4712 : if (xtext.is())
603 [ + - ][ + - ]: 4712 : return xtext->getNodeValue();
[ + - ][ - + ]
604 : : }
605 : 4718 : return ::rtl::OUString();
606 : : }
607 : :
608 : 0 : ::rtl::OUString DescriptionInfoset::getLocalizedLicenseURL() const
609 : : {
610 : : return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
611 [ # # ]: 0 : "/desc:description/desc:registration/desc:simple-license")), NULL);
612 : :
613 : : }
614 : :
615 : : ::boost::optional<SimpleLicenseAttributes>
616 : 994 : DescriptionInfoset::getSimpleLicenseAttributes() const
617 : : {
618 : : //Check if the node exist
619 : 994 : css::uno::Reference< css::xml::dom::XNode > n;
620 [ + + ]: 994 : if (m_element.is()) {
621 : : try {
622 [ + - ]: 992 : n = m_xpath->selectSingleNode(m_element,
623 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
624 [ + - ][ + - ]: 992 : "/desc:description/desc:registration/desc:simple-license/@accept-by")));
[ + - ][ # # ]
625 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
626 : : // ignore
627 : : }
628 [ - + ]: 992 : if (n.is())
629 : : {
630 [ # # ]: 0 : SimpleLicenseAttributes attributes;
631 : : attributes.acceptBy =
632 : : getNodeValueFromExpression(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
633 [ # # ][ # # ]: 0 : "/desc:description/desc:registration/desc:simple-license/@accept-by")));
634 : :
635 : : ::boost::optional< ::rtl::OUString > suppressOnUpdate = getOptionalValue(
636 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
637 [ # # ][ # # ]: 0 : "/desc:description/desc:registration/desc:simple-license/@suppress-on-update")));
638 [ # # ][ # # ]: 0 : if (suppressOnUpdate)
639 [ # # ]: 0 : attributes.suppressOnUpdate = (*suppressOnUpdate).trim().equalsIgnoreAsciiCase(
640 [ # # ]: 0 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
641 : : else
642 : 0 : attributes.suppressOnUpdate = false;
643 : :
644 : : ::boost::optional< ::rtl::OUString > suppressIfRequired = getOptionalValue(
645 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
646 [ # # ][ # # ]: 0 : "/desc:description/desc:registration/desc:simple-license/@suppress-if-required")));
647 [ # # ][ # # ]: 0 : if (suppressIfRequired)
648 [ # # ]: 0 : attributes.suppressIfRequired = (*suppressIfRequired).trim().equalsIgnoreAsciiCase(
649 [ # # ]: 0 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
650 : : else
651 : 0 : attributes.suppressIfRequired = false;
652 : :
653 [ # # ][ # # ]: 0 : return ::boost::optional<SimpleLicenseAttributes>(attributes);
[ # # ][ # # ]
654 : : }
655 : : }
656 [ + - ]: 994 : return ::boost::optional<SimpleLicenseAttributes>();
657 : : }
658 : :
659 : 0 : ::rtl::OUString DescriptionInfoset::getLocalizedDescriptionURL() const
660 : : {
661 : : return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
662 [ # # ]: 0 : "/desc:description/desc:extension-description")), NULL);
663 : : }
664 : :
665 : : css::uno::Reference< css::xml::dom::XNode >
666 : 4718 : DescriptionInfoset::getLocalizedChild( const ::rtl::OUString & sParent) const
667 : : {
668 [ + + ][ - + ]: 4718 : if ( ! m_element.is() || sParent.isEmpty())
[ + + ]
669 : 6 : return css::uno::Reference< css::xml::dom::XNode > ();
670 : :
671 : 4712 : css::uno::Reference< css::xml::dom::XNode > xParent;
672 : : try {
673 [ + - ][ + - ]: 4712 : xParent = m_xpath->selectSingleNode(m_element, sParent);
[ # # ][ + - ]
674 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
675 : : // ignore
676 : : }
677 : 4712 : css::uno::Reference<css::xml::dom::XNode> nodeMatch;
678 [ + - ]: 4712 : if (xParent.is())
679 : : {
680 [ + - ]: 4712 : const ::rtl::OUString sLocale = getOfficeLocaleString();
681 [ + - ][ + - ]: 4712 : nodeMatch = matchFullLocale(xParent, sLocale);
682 : :
683 : : //office: en-DE, en, en-DE-altmark
684 [ - + ]: 4712 : if (! nodeMatch.is())
685 : : {
686 [ # # ]: 0 : const css::lang::Locale officeLocale = getOfficeLocale();
687 [ # # ][ # # ]: 0 : nodeMatch = matchCountryAndLanguage(xParent, officeLocale);
688 [ # # ]: 0 : if ( ! nodeMatch.is())
689 : : {
690 [ # # ][ # # ]: 0 : nodeMatch = matchLanguage(xParent, officeLocale);
691 [ # # ]: 0 : if (! nodeMatch.is())
692 [ # # ][ # # ]: 0 : nodeMatch = getChildWithDefaultLocale(xParent);
693 : 0 : }
694 : 4712 : }
695 : : }
696 : :
697 : 4718 : return nodeMatch;
698 : : }
699 : :
700 : : css::uno::Reference<css::xml::dom::XNode>
701 : 4712 : DescriptionInfoset::matchFullLocale(css::uno::Reference< css::xml::dom::XNode >
702 : : const & xParent, ::rtl::OUString const & sLocale) const
703 : : {
704 : : OSL_ASSERT(xParent.is());
705 : : const ::rtl::OUString exp1(
706 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
707 : : + sLocale +
708 [ + - ][ + - ]: 4712 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
709 : : try {
710 [ + - ][ + - ]: 4712 : return m_xpath->selectSingleNode(xParent, exp1);
711 [ # # # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
712 : : // ignore
713 [ # # ]: 0 : return 0;
714 : 4712 : }
715 : : }
716 : :
717 : : css::uno::Reference<css::xml::dom::XNode>
718 : 0 : DescriptionInfoset::matchCountryAndLanguage(
719 : : css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
720 : : {
721 : : OSL_ASSERT(xParent.is());
722 : 0 : css::uno::Reference<css::xml::dom::XNode> nodeMatch;
723 : :
724 [ # # ]: 0 : if (!officeLocale.Country.isEmpty())
725 : : {
726 : : const ::rtl::OUString sLangCountry(officeLocale.Language +
727 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) +
728 [ # # ]: 0 : officeLocale.Country);
729 : : //first try exact match for lang-country
730 : : const ::rtl::OUString exp1(
731 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
732 : : + sLangCountry +
733 [ # # ][ # # ]: 0 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
734 : : try {
735 [ # # ][ # # ]: 0 : nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
[ # # ][ # # ]
736 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
737 : : // ignore
738 : : }
739 : :
740 : : //try to match in strings that also have a variant, for example en-US matches in
741 : : //en-US-montana
742 [ # # ]: 0 : if (!nodeMatch.is())
743 : : {
744 : : const ::rtl::OUString exp2(
745 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
746 : : + sLangCountry +
747 [ # # ][ # # ]: 0 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
748 : : try {
749 [ # # ][ # # ]: 0 : nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
[ # # ][ # # ]
750 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
751 : : // ignore
752 : 0 : }
753 : 0 : }
754 : : }
755 : :
756 : 0 : return nodeMatch;
757 : : }
758 : :
759 : :
760 : : css::uno::Reference<css::xml::dom::XNode>
761 : 0 : DescriptionInfoset::matchLanguage(
762 : : css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
763 : : {
764 : : OSL_ASSERT(xParent.is());
765 : 0 : css::uno::Reference<css::xml::dom::XNode> nodeMatch;
766 : :
767 : : //first try exact match for lang
768 : : const ::rtl::OUString exp1(
769 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
770 : : + officeLocale.Language
771 [ # # ][ # # ]: 0 : + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
772 : : try {
773 [ # # ][ # # ]: 0 : nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
[ # # ][ # # ]
774 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
775 : : // ignore
776 : : }
777 : :
778 : : //try to match in strings that also have a country and/orvariant, for example en matches in
779 : : //en-US-montana, en-US, en-montana
780 [ # # ]: 0 : if (!nodeMatch.is())
781 : : {
782 : : const ::rtl::OUString exp2(
783 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
784 : : + officeLocale.Language
785 [ # # ][ # # ]: 0 : + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
786 : : try {
787 [ # # ][ # # ]: 0 : nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
[ # # ][ # # ]
788 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
789 : : // ignore
790 : 0 : }
791 : : }
792 : 0 : return nodeMatch;
793 : : }
794 : :
795 : : css::uno::Reference<css::xml::dom::XNode>
796 : 0 : DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference< css::xml::dom::XNode >
797 : : const & xParent) const
798 : : {
799 : : OSL_ASSERT(xParent.is());
800 [ # # ][ # # ]: 0 : if ( xParent->getNodeName() == "simple-license" )
[ # # ]
801 : : {
802 : 0 : css::uno::Reference<css::xml::dom::XNode> nodeDefault;
803 : : try {
804 [ # # ]: 0 : nodeDefault = m_xpath->selectSingleNode(xParent, ::rtl::OUString(
805 [ # # ][ # # ]: 0 : RTL_CONSTASCII_USTRINGPARAM("@default-license-id")));
[ # # ][ # # ]
806 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
807 : : // ignore
808 : : }
809 [ # # ]: 0 : if (nodeDefault.is())
810 : : {
811 : : //The old way
812 : : const ::rtl::OUString exp1(
813 : : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \""))
814 [ # # ]: 0 : + nodeDefault->getNodeValue()
815 [ # # ][ # # ]: 0 : + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
[ # # ][ # # ]
816 : : try {
817 [ # # ][ # # ]: 0 : return m_xpath->selectSingleNode(xParent, exp1);
818 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
819 : : // ignore
820 [ # # ]: 0 : }
821 [ # # ]: 0 : }
822 : : }
823 : :
824 [ # # ]: 0 : const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]"));
825 : : try {
826 [ # # ][ # # ]: 0 : return m_xpath->selectSingleNode(xParent, exp2);
827 [ # # # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
828 : : // ignore
829 [ # # ]: 0 : return 0;
830 : 0 : }
831 : : }
832 : :
833 : 0 : ::rtl::OUString DescriptionInfoset::getLocalizedHREFAttrFromChild(
834 : : ::rtl::OUString const & sXPathParent, bool * out_bParentExists)
835 : : const
836 : : {
837 : : css::uno::Reference< css::xml::dom::XNode > node =
838 [ # # ]: 0 : getLocalizedChild(sXPathParent);
839 : :
840 : 0 : ::rtl::OUString sURL;
841 [ # # ]: 0 : if (node.is())
842 : : {
843 [ # # ]: 0 : if (out_bParentExists)
844 : 0 : *out_bParentExists = true;
845 [ # # ]: 0 : const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
846 : 0 : css::uno::Reference< css::xml::dom::XNode > xURL;
847 : : try {
848 [ # # ][ # # ]: 0 : xURL = m_xpath->selectSingleNode(node, exp);
[ # # ][ # # ]
849 [ # # ]: 0 : } catch (const css::xml::xpath::XPathException &) {
850 : : // ignore
851 : : }
852 : : OSL_ASSERT(xURL.is());
853 [ # # ]: 0 : if (xURL.is())
854 [ # # ][ # # ]: 0 : sURL = xURL->getNodeValue();
855 : : }
856 : : else
857 : : {
858 [ # # ]: 0 : if (out_bParentExists)
859 : 0 : *out_bParentExists = false;
860 : : }
861 : 0 : return sURL;
862 : : }
863 : :
864 : : }
865 : :
866 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|