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