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"
379e813386SMichael Stahl #include "comphelper/seqstream.hxx"
38cdf0e10cSrcweir #include "comphelper/makesequence.hxx"
39cdf0e10cSrcweir #include "comphelper/processfactory.hxx"
40cdf0e10cSrcweir #include "boost/optional.hpp"
419e813386SMichael Stahl #include "com/sun/star/container/XNameAccess.hpp"
42cdf0e10cSrcweir #include "com/sun/star/beans/Optional.hpp"
439e813386SMichael Stahl #include "com/sun/star/beans/PropertyValue.hpp"
449e813386SMichael Stahl #include "com/sun/star/beans/XPropertySet.hpp"
459e813386SMichael 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):
3739e813386SMichael 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 
4169e813386SMichael Stahl void DescriptionInfoset::checkBlacklist() const
4179e813386SMichael Stahl {
4189e813386SMichael Stahl     if (m_element.is()) {
4199e813386SMichael Stahl         boost::optional< OUString > id(getIdentifier());
4209e813386SMichael Stahl         if (!id)
4219e813386SMichael Stahl             return; // nothing to check
4229e813386SMichael Stahl         OUString currentversion(getVersion());
4239e813386SMichael Stahl         if (currentversion.getLength() == 0)
4249e813386SMichael Stahl             return;  // nothing to check
4259e813386SMichael Stahl 
4269e813386SMichael Stahl         css::uno::Reference< css::lang::XMultiComponentFactory > manager(
4279e813386SMichael Stahl             m_context->getServiceManager(), css::uno::UNO_QUERY_THROW);
4289e813386SMichael Stahl         css::uno::Reference< css::lang::XMultiServiceFactory> provider(
4299e813386SMichael Stahl             manager->createInstanceWithContext(
4309e813386SMichael Stahl                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")), m_context),
4319e813386SMichael Stahl                 css::uno::UNO_QUERY_THROW);
4329e813386SMichael Stahl 
4339e813386SMichael Stahl         css::uno::Sequence< css::uno::Any > args = css::uno::Sequence< css::uno::Any >(1);
4349e813386SMichael Stahl         css::beans::PropertyValue prop;
4359e813386SMichael Stahl         prop.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath"));
4369e813386SMichael Stahl         prop.Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.ExtensionDependencies/Extensions"));
4379e813386SMichael Stahl         args[0] <<= prop;
4389e813386SMichael Stahl 
4399e813386SMichael Stahl         css::uno::Reference< css::container::XNameAccess > blacklist(
4409e813386SMichael Stahl             provider->createInstanceWithArguments(
4419e813386SMichael Stahl                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), args),
4429e813386SMichael Stahl                 css::uno::UNO_QUERY_THROW);
4439e813386SMichael Stahl 
4449e813386SMichael Stahl         // check first if a blacklist entry is available
4459e813386SMichael Stahl         if (blacklist.is() && blacklist->hasByName(*id)) {
4469e813386SMichael Stahl             css::uno::Reference< css::beans::XPropertySet > extProps(
4479e813386SMichael Stahl                 blacklist->getByName(*id), css::uno::UNO_QUERY_THROW);
4489e813386SMichael Stahl 
4499e813386SMichael Stahl             css::uno::Any anyValue = extProps->getPropertyValue(
4509e813386SMichael Stahl                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Versions")));
4519e813386SMichael Stahl 
4529e813386SMichael Stahl             css::uno::Sequence< ::rtl::OUString > blversions;
4539e813386SMichael Stahl             anyValue >>= blversions;
4549e813386SMichael Stahl 
4559e813386SMichael Stahl             // check if the current version requires further dependency checks from the blacklist
4569e813386SMichael Stahl             if (checkBlacklistVersion(currentversion, blversions)) {
4579e813386SMichael Stahl                 anyValue = extProps->getPropertyValue(
4589e813386SMichael Stahl                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Dependencies")));
4599e813386SMichael Stahl                 ::rtl::OUString udeps;
4609e813386SMichael Stahl                 anyValue >>= udeps;
4619e813386SMichael Stahl 
4629e813386SMichael Stahl                 if (udeps.getLength() == 0)
4639e813386SMichael Stahl                     return; // nothing todo
4649e813386SMichael Stahl 
4659e813386SMichael Stahl                 ::rtl::OString xmlDependencies = ::rtl::OUStringToOString(udeps, RTL_TEXTENCODING_UNICODE);
4669e813386SMichael Stahl 
4679e813386SMichael Stahl                 css::uno::Reference< css::xml::dom::XDocumentBuilder> docbuilder(
4689e813386SMichael Stahl                     manager->createInstanceWithContext(
4699e813386SMichael Stahl                         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder")), m_context),
4709e813386SMichael Stahl                     css::uno::UNO_QUERY_THROW);
4719e813386SMichael Stahl 
4729e813386SMichael Stahl                 css::uno::Sequence< sal_Int8 > byteSeq((const sal_Int8*)xmlDependencies.getStr(), xmlDependencies.getLength());
4739e813386SMichael Stahl 
4749e813386SMichael Stahl                 css::uno::Reference< css::io::XInputStream> inputstream( css::io::SequenceInputStream::createStreamFromSequence(m_context, byteSeq),
4759e813386SMichael Stahl                                                                          css::uno::UNO_QUERY_THROW);
4769e813386SMichael Stahl 
4779e813386SMichael Stahl                 css::uno::Reference< css::xml::dom::XDocument > xDocument(docbuilder->parse(inputstream));
4789e813386SMichael Stahl                 css::uno::Reference< css::xml::dom::XElement > xElement(xDocument->getDocumentElement());
4799e813386SMichael Stahl                 css::uno::Reference< css::xml::dom::XNodeList > xDeps(xElement->getChildNodes());
4809e813386SMichael Stahl                 sal_Int32 nLen = xDeps->getLength();
4819e813386SMichael Stahl 
482*2bc1ebb7SMichael Stahl                 // get the parent xml document  of current description info for the import
483*2bc1ebb7SMichael Stahl                 css::uno::Reference< css::xml::dom::XDocument > xCurrentDescInfo(m_element->getOwnerDocument());
484*2bc1ebb7SMichael Stahl 
4859e813386SMichael Stahl                 // get dependency node of current description info to merge the new dependencies from the blacklist
4869e813386SMichael Stahl                 css::uno::Reference< css::xml::dom::XNode > xCurrentDeps(
4879e813386SMichael Stahl                     m_xpath->selectSingleNode(m_element, ::rtl::OUString(
4889e813386SMichael Stahl                                                   RTL_CONSTASCII_USTRINGPARAM("desc:dependencies"))));
4899e813386SMichael Stahl 
490*2bc1ebb7SMichael Stahl                 // if no dependency node exists, create a new one in the current description info
491*2bc1ebb7SMichael Stahl                 if (!xCurrentDeps.is()) {
492*2bc1ebb7SMichael Stahl                     css::uno::Reference< css::xml::dom::XNode > xNewDepNode(
493*2bc1ebb7SMichael Stahl                         xCurrentDescInfo->createElementNS(
494*2bc1ebb7SMichael Stahl                             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http://openoffice.org/extensions/description/2006")),
495*2bc1ebb7SMichael Stahl                             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dependencies"))), css::uno::UNO_QUERY_THROW);
496*2bc1ebb7SMichael Stahl                     m_element->appendChild(xNewDepNode);
497*2bc1ebb7SMichael Stahl                     xCurrentDeps = m_xpath->selectSingleNode(m_element, ::rtl::OUString(
498*2bc1ebb7SMichael Stahl                                                   RTL_CONSTASCII_USTRINGPARAM("desc:dependencies")));
499*2bc1ebb7SMichael Stahl                 }
5009e813386SMichael Stahl 
5019e813386SMichael Stahl                 for (sal_Int32 i=0; i<nLen; i++) {
5029e813386SMichael Stahl                     css::uno::Reference< css::xml::dom::XNode > xNode(xDeps->item(i));
5039e813386SMichael Stahl                     css::uno::Reference< css::xml::dom::XElement > xDep(xNode, css::uno::UNO_QUERY);
5049e813386SMichael Stahl                     if (xDep.is()) {
5059e813386SMichael Stahl                         // found valid blacklist dependency, import the node first and append it to the existing dependency node
5069e813386SMichael Stahl                         css::uno::Reference< css::xml::dom::XNode > importedNode = xCurrentDescInfo->importNode(xNode, true);
5079e813386SMichael Stahl                         xCurrentDeps->appendChild(importedNode);
5089e813386SMichael Stahl                     }
5099e813386SMichael Stahl                 }
5109e813386SMichael Stahl             }
5119e813386SMichael Stahl         }
5129e813386SMichael Stahl     }
5139e813386SMichael Stahl }
5149e813386SMichael Stahl 
5159e813386SMichael Stahl bool DescriptionInfoset::checkBlacklistVersion(
5169e813386SMichael Stahl     ::rtl::OUString currentversion,
5179e813386SMichael Stahl     ::com::sun::star::uno::Sequence< ::rtl::OUString > const & versions) const
5189e813386SMichael Stahl {
5199e813386SMichael Stahl     sal_Int32 nLen = versions.getLength();
5209e813386SMichael Stahl     for (sal_Int32 i=0; i<nLen; i++) {
5219e813386SMichael Stahl         if (currentversion.equals(versions[i]))
5229e813386SMichael Stahl             return true;
5239e813386SMichael Stahl     }
5249e813386SMichael Stahl 
5259e813386SMichael Stahl     return false;
5269e813386SMichael Stahl }
527cdf0e10cSrcweir 
528cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getVersion() const
529cdf0e10cSrcweir {
530cdf0e10cSrcweir     return getNodeValueFromExpression( ::rtl::OUString(
531cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM("desc:version/@value")));
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getSupportedPlaforms() const
535cdf0e10cSrcweir {
536cdf0e10cSrcweir     //When there is no description.xml then we assume that we support all platforms
537cdf0e10cSrcweir     if (! m_element.is())
538cdf0e10cSrcweir     {
539cdf0e10cSrcweir         return comphelper::makeSequence(
540cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir 
543cdf0e10cSrcweir     //Check if the <platform> element was provided. If not the default is "all" platforms
544cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > nodePlatform(
545cdf0e10cSrcweir         m_xpath->selectSingleNode(m_element, ::rtl::OUString(
546cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM("desc:platform"))));
547cdf0e10cSrcweir     if (!nodePlatform.is())
548cdf0e10cSrcweir     {
549cdf0e10cSrcweir         return comphelper::makeSequence(
550cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
551cdf0e10cSrcweir     }
552cdf0e10cSrcweir 
553cdf0e10cSrcweir     //There is a platform element.
554cdf0e10cSrcweir     const ::rtl::OUString value = getNodeValueFromExpression(::rtl::OUString(
555cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value")));
556cdf0e10cSrcweir     //parse the string, it can contained multiple strings separated by commas
557cdf0e10cSrcweir     ::std::vector< ::rtl::OUString> vec;
558cdf0e10cSrcweir     sal_Int32 nIndex = 0;
559cdf0e10cSrcweir     do
560cdf0e10cSrcweir     {
561cdf0e10cSrcweir         ::rtl::OUString aToken = value.getToken( 0, ',', nIndex );
562cdf0e10cSrcweir         aToken = aToken.trim();
563cdf0e10cSrcweir         if (aToken.getLength())
564cdf0e10cSrcweir             vec.push_back(aToken);
5659e813386SMichael Stahl 
566cdf0e10cSrcweir     }
567cdf0e10cSrcweir     while (nIndex >= 0);
568cdf0e10cSrcweir 
569cdf0e10cSrcweir     return comphelper::containerToSequence(vec);
570cdf0e10cSrcweir }
571cdf0e10cSrcweir 
572cdf0e10cSrcweir css::uno::Reference< css::xml::dom::XNodeList >
573cdf0e10cSrcweir DescriptionInfoset::getDependencies() const {
574cdf0e10cSrcweir     if (m_element.is()) {
575cdf0e10cSrcweir         try {
5769e813386SMichael Stahl             // check the extension blacklist first and expand the dependencies if applicable
5779e813386SMichael Stahl             checkBlacklist();
5789e813386SMichael Stahl 
579cdf0e10cSrcweir             return m_xpath->selectNodeList(m_element, ::rtl::OUString(
580cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*")));
581cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
582cdf0e10cSrcweir             // ignore
583cdf0e10cSrcweir         }
584cdf0e10cSrcweir     }
585cdf0e10cSrcweir     return new EmptyNodeList;
586cdf0e10cSrcweir }
587cdf0e10cSrcweir 
588cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString >
589cdf0e10cSrcweir DescriptionInfoset::getUpdateInformationUrls() const {
590cdf0e10cSrcweir     return getUrls(
591cdf0e10cSrcweir         ::rtl::OUString(
592cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM(
593cdf0e10cSrcweir                 "desc:update-information/desc:src/@xlink:href")));
594cdf0e10cSrcweir }
595cdf0e10cSrcweir 
596cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString >
597cdf0e10cSrcweir DescriptionInfoset::getUpdateDownloadUrls() const
598cdf0e10cSrcweir {
599cdf0e10cSrcweir     return getUrls(
600cdf0e10cSrcweir         ::rtl::OUString(
601cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM(
602cdf0e10cSrcweir                 "desc:update-download/desc:src/@xlink:href")));
603cdf0e10cSrcweir }
604cdf0e10cSrcweir 
605cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getIconURL( sal_Bool bHighContrast ) const
606cdf0e10cSrcweir {
607cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > aStrList = getUrls( ::rtl::OUString(
608cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href")));
609cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > aStrListHC = getUrls( ::rtl::OUString(
610cdf0e10cSrcweir             RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href")));
611cdf0e10cSrcweir 
612cdf0e10cSrcweir     if ( bHighContrast && aStrListHC.hasElements() && aStrListHC[0].getLength() )
613cdf0e10cSrcweir         return aStrListHC[0];
614cdf0e10cSrcweir 
615cdf0e10cSrcweir     if ( aStrList.hasElements() && aStrList[0].getLength() )
616cdf0e10cSrcweir         return aStrList[0];
617cdf0e10cSrcweir 
618cdf0e10cSrcweir     return ::rtl::OUString();
619cdf0e10cSrcweir }
620cdf0e10cSrcweir 
621cdf0e10cSrcweir ::boost::optional< ::rtl::OUString > DescriptionInfoset::getLocalizedUpdateWebsiteURL()
622cdf0e10cSrcweir     const
623cdf0e10cSrcweir {
624cdf0e10cSrcweir     bool bParentExists = false;
625cdf0e10cSrcweir     const ::rtl::OUString sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
626cdf0e10cSrcweir         "/desc:description/desc:update-website")), &bParentExists ));
627cdf0e10cSrcweir 
628cdf0e10cSrcweir     if (sURL.getLength() > 0)
629cdf0e10cSrcweir         return ::boost::optional< ::rtl::OUString >(sURL);
630cdf0e10cSrcweir     else
631cdf0e10cSrcweir         return bParentExists ? ::boost::optional< ::rtl::OUString >(::rtl::OUString()) :
632cdf0e10cSrcweir             ::boost::optional< ::rtl::OUString >();
633cdf0e10cSrcweir }
634cdf0e10cSrcweir 
635cdf0e10cSrcweir ::boost::optional< ::rtl::OUString > DescriptionInfoset::getOptionalValue(
636cdf0e10cSrcweir     ::rtl::OUString const & expression) const
637cdf0e10cSrcweir {
638cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > n;
639cdf0e10cSrcweir     if (m_element.is()) {
640cdf0e10cSrcweir         try {
641cdf0e10cSrcweir             n = m_xpath->selectSingleNode(m_element, expression);
642cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
643cdf0e10cSrcweir             // ignore
644cdf0e10cSrcweir         }
645cdf0e10cSrcweir     }
646cdf0e10cSrcweir     return n.is()
647cdf0e10cSrcweir         ? ::boost::optional< ::rtl::OUString >(getNodeValue(n))
648cdf0e10cSrcweir         : ::boost::optional< ::rtl::OUString >();
649cdf0e10cSrcweir }
650cdf0e10cSrcweir 
651cdf0e10cSrcweir css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getUrls(
652cdf0e10cSrcweir     ::rtl::OUString const & expression) const
653cdf0e10cSrcweir {
654cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNodeList > ns;
655cdf0e10cSrcweir     if (m_element.is()) {
656cdf0e10cSrcweir         try {
657cdf0e10cSrcweir             ns = m_xpath->selectNodeList(m_element, expression);
658cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
659cdf0e10cSrcweir             // ignore
660cdf0e10cSrcweir         }
661cdf0e10cSrcweir     }
662cdf0e10cSrcweir     css::uno::Sequence< ::rtl::OUString > urls(ns.is() ? ns->getLength() : 0);
663cdf0e10cSrcweir     for (::sal_Int32 i = 0; i < urls.getLength(); ++i) {
664cdf0e10cSrcweir         urls[i] = getNodeValue(ns->item(i));
665cdf0e10cSrcweir     }
666cdf0e10cSrcweir     return urls;
667cdf0e10cSrcweir }
668cdf0e10cSrcweir 
669cdf0e10cSrcweir ::std::pair< ::rtl::OUString, ::rtl::OUString > DescriptionInfoset::getLocalizedPublisherNameAndURL() const
670cdf0e10cSrcweir {
671cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > node =
672cdf0e10cSrcweir         getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher")));
673cdf0e10cSrcweir 
674cdf0e10cSrcweir     ::rtl::OUString sPublisherName;
675cdf0e10cSrcweir     ::rtl::OUString sURL;
676cdf0e10cSrcweir     if (node.is())
677cdf0e10cSrcweir     {
678cdf0e10cSrcweir         const ::rtl::OUString exp1(RTL_CONSTASCII_USTRINGPARAM("text()"));
679cdf0e10cSrcweir         css::uno::Reference< css::xml::dom::XNode > xPathName;
680cdf0e10cSrcweir         try {
681cdf0e10cSrcweir             xPathName = m_xpath->selectSingleNode(node, exp1);
682cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
683cdf0e10cSrcweir             // ignore
684cdf0e10cSrcweir         }
685cdf0e10cSrcweir         OSL_ASSERT(xPathName.is());
686cdf0e10cSrcweir         if (xPathName.is())
687cdf0e10cSrcweir             sPublisherName = xPathName->getNodeValue();
688cdf0e10cSrcweir 
689cdf0e10cSrcweir         const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
690cdf0e10cSrcweir         css::uno::Reference< css::xml::dom::XNode > xURL;
691cdf0e10cSrcweir         try {
692cdf0e10cSrcweir             xURL = m_xpath->selectSingleNode(node, exp2);
693cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
694cdf0e10cSrcweir             // ignore
695cdf0e10cSrcweir         }
696cdf0e10cSrcweir         OSL_ASSERT(xURL.is());
697cdf0e10cSrcweir         if (xURL.is())
698cdf0e10cSrcweir            sURL = xURL->getNodeValue();
699cdf0e10cSrcweir     }
700cdf0e10cSrcweir     return ::std::make_pair(sPublisherName, sURL);
701cdf0e10cSrcweir }
702cdf0e10cSrcweir 
703cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getLocalizedReleaseNotesURL() const
704cdf0e10cSrcweir {
705cdf0e10cSrcweir     return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
706cdf0e10cSrcweir         "/desc:description/desc:release-notes")), NULL);
707cdf0e10cSrcweir }
708cdf0e10cSrcweir 
709cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getLocalizedDisplayName() const
710cdf0e10cSrcweir {
711cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > node =
712cdf0e10cSrcweir         getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name")));
713cdf0e10cSrcweir     if (node.is())
714cdf0e10cSrcweir     {
715cdf0e10cSrcweir         const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("text()"));
716cdf0e10cSrcweir         css::uno::Reference< css::xml::dom::XNode > xtext;
717cdf0e10cSrcweir         try {
718cdf0e10cSrcweir             xtext = m_xpath->selectSingleNode(node, exp);
719cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
720cdf0e10cSrcweir             // ignore
721cdf0e10cSrcweir         }
722cdf0e10cSrcweir         if (xtext.is())
723cdf0e10cSrcweir             return xtext->getNodeValue();
724cdf0e10cSrcweir     }
725cdf0e10cSrcweir     return ::rtl::OUString();
726cdf0e10cSrcweir }
727cdf0e10cSrcweir 
728cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getLocalizedLicenseURL() const
729cdf0e10cSrcweir {
730cdf0e10cSrcweir     return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
731cdf0e10cSrcweir         "/desc:description/desc:registration/desc:simple-license")), NULL);
732cdf0e10cSrcweir 
733cdf0e10cSrcweir }
734cdf0e10cSrcweir 
735cdf0e10cSrcweir ::boost::optional<SimpleLicenseAttributes>
736cdf0e10cSrcweir DescriptionInfoset::getSimpleLicenseAttributes() const
737cdf0e10cSrcweir {
738cdf0e10cSrcweir     //Check if the node exist
739cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > n;
740cdf0e10cSrcweir     if (m_element.is()) {
741cdf0e10cSrcweir         try {
742cdf0e10cSrcweir             n = m_xpath->selectSingleNode(m_element,
743cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
744cdf0e10cSrcweir                 "/desc:description/desc:registration/desc:simple-license/@accept-by")));
745cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
746cdf0e10cSrcweir             // ignore
747cdf0e10cSrcweir         }
748cdf0e10cSrcweir         if (n.is())
749cdf0e10cSrcweir         {
750cdf0e10cSrcweir             SimpleLicenseAttributes attributes;
751cdf0e10cSrcweir             attributes.acceptBy =
752cdf0e10cSrcweir                 getNodeValueFromExpression(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
753cdf0e10cSrcweir                 "/desc:description/desc:registration/desc:simple-license/@accept-by")));
754cdf0e10cSrcweir 
755cdf0e10cSrcweir             ::boost::optional< ::rtl::OUString > suppressOnUpdate = getOptionalValue(
756cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
757cdf0e10cSrcweir                 "/desc:description/desc:registration/desc:simple-license/@suppress-on-update")));
758cdf0e10cSrcweir             if (suppressOnUpdate)
759cdf0e10cSrcweir                 attributes.suppressOnUpdate = (*suppressOnUpdate).trim().equalsIgnoreAsciiCase(
760cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
761cdf0e10cSrcweir             else
762cdf0e10cSrcweir                 attributes.suppressOnUpdate = false;
763cdf0e10cSrcweir 
764cdf0e10cSrcweir             ::boost::optional< ::rtl::OUString > suppressIfRequired = getOptionalValue(
765cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
766cdf0e10cSrcweir                 "/desc:description/desc:registration/desc:simple-license/@suppress-if-required")));
767cdf0e10cSrcweir             if (suppressIfRequired)
768cdf0e10cSrcweir                 attributes.suppressIfRequired = (*suppressIfRequired).trim().equalsIgnoreAsciiCase(
769cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
770cdf0e10cSrcweir             else
771cdf0e10cSrcweir                 attributes.suppressIfRequired = false;
772cdf0e10cSrcweir 
773cdf0e10cSrcweir             return ::boost::optional<SimpleLicenseAttributes>(attributes);
774cdf0e10cSrcweir         }
775cdf0e10cSrcweir     }
776cdf0e10cSrcweir     return ::boost::optional<SimpleLicenseAttributes>();
777cdf0e10cSrcweir }
778cdf0e10cSrcweir 
779cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getLocalizedDescriptionURL() const
780cdf0e10cSrcweir {
781cdf0e10cSrcweir     return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
782cdf0e10cSrcweir         "/desc:description/desc:extension-description")), NULL);
783cdf0e10cSrcweir }
784cdf0e10cSrcweir 
785cdf0e10cSrcweir css::uno::Reference< css::xml::dom::XNode >
786cdf0e10cSrcweir DescriptionInfoset::getLocalizedChild( const ::rtl::OUString & sParent) const
787cdf0e10cSrcweir {
788cdf0e10cSrcweir     if ( ! m_element.is() || !sParent.getLength())
789cdf0e10cSrcweir         return css::uno::Reference< css::xml::dom::XNode > ();
790cdf0e10cSrcweir 
791cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > xParent;
792cdf0e10cSrcweir     try {
793cdf0e10cSrcweir         xParent = m_xpath->selectSingleNode(m_element, sParent);
794cdf0e10cSrcweir     } catch (css::xml::xpath::XPathException &) {
795cdf0e10cSrcweir         // ignore
796cdf0e10cSrcweir     }
797cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> nodeMatch;
798cdf0e10cSrcweir     if (xParent.is())
799cdf0e10cSrcweir     {
800cdf0e10cSrcweir         const ::rtl::OUString sLocale = getOfficeLocaleString();
801cdf0e10cSrcweir         nodeMatch = matchFullLocale(xParent, sLocale);
802cdf0e10cSrcweir 
803cdf0e10cSrcweir         //office: en-DE, en, en-DE-altmark
804cdf0e10cSrcweir         if (! nodeMatch.is())
805cdf0e10cSrcweir         {
806cdf0e10cSrcweir             const css::lang::Locale officeLocale = getOfficeLocale();
807cdf0e10cSrcweir             nodeMatch = matchCountryAndLanguage(xParent, officeLocale);
808cdf0e10cSrcweir             if ( ! nodeMatch.is())
809cdf0e10cSrcweir             {
810cdf0e10cSrcweir                 nodeMatch = matchLanguage(xParent, officeLocale);
811cdf0e10cSrcweir                 if (! nodeMatch.is())
812cdf0e10cSrcweir                     nodeMatch = getChildWithDefaultLocale(xParent);
813cdf0e10cSrcweir             }
814cdf0e10cSrcweir         }
815cdf0e10cSrcweir     }
816cdf0e10cSrcweir 
817cdf0e10cSrcweir     return nodeMatch;
818cdf0e10cSrcweir }
819cdf0e10cSrcweir 
820cdf0e10cSrcweir css::uno::Reference<css::xml::dom::XNode>
821cdf0e10cSrcweir DescriptionInfoset::matchFullLocale(css::uno::Reference< css::xml::dom::XNode >
822cdf0e10cSrcweir                                     const & xParent, ::rtl::OUString const & sLocale) const
823cdf0e10cSrcweir {
824cdf0e10cSrcweir     OSL_ASSERT(xParent.is());
825cdf0e10cSrcweir     const ::rtl::OUString exp1(
826cdf0e10cSrcweir         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
827cdf0e10cSrcweir         + sLocale +
828cdf0e10cSrcweir         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
829cdf0e10cSrcweir     try {
830cdf0e10cSrcweir         return m_xpath->selectSingleNode(xParent, exp1);
831cdf0e10cSrcweir     } catch (css::xml::xpath::XPathException &) {
832cdf0e10cSrcweir         // ignore
833cdf0e10cSrcweir         return 0;
834cdf0e10cSrcweir     }
835cdf0e10cSrcweir }
836cdf0e10cSrcweir 
837cdf0e10cSrcweir css::uno::Reference<css::xml::dom::XNode>
838cdf0e10cSrcweir DescriptionInfoset::matchCountryAndLanguage(
839cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
840cdf0e10cSrcweir {
841cdf0e10cSrcweir     OSL_ASSERT(xParent.is());
842cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> nodeMatch;
843cdf0e10cSrcweir 
844cdf0e10cSrcweir     if (officeLocale.Country.getLength())
845cdf0e10cSrcweir     {
846cdf0e10cSrcweir         const ::rtl::OUString sLangCountry(officeLocale.Language +
847cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) +
848cdf0e10cSrcweir             officeLocale.Country);
849cdf0e10cSrcweir         //first try exact match for lang-country
850cdf0e10cSrcweir         const ::rtl::OUString exp1(
851cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
852cdf0e10cSrcweir             + sLangCountry +
853cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
854cdf0e10cSrcweir         try {
855cdf0e10cSrcweir             nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
856cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
857cdf0e10cSrcweir             // ignore
858cdf0e10cSrcweir         }
859cdf0e10cSrcweir 
860cdf0e10cSrcweir         //try to match in strings that also have a variant, for example en-US matches in
861cdf0e10cSrcweir         //en-US-montana
862cdf0e10cSrcweir         if (!nodeMatch.is())
863cdf0e10cSrcweir         {
864cdf0e10cSrcweir             const ::rtl::OUString exp2(
865cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
866cdf0e10cSrcweir                 + sLangCountry +
867cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
868cdf0e10cSrcweir             try {
869cdf0e10cSrcweir                 nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
870cdf0e10cSrcweir             } catch (css::xml::xpath::XPathException &) {
871cdf0e10cSrcweir                 // ignore
872cdf0e10cSrcweir             }
873cdf0e10cSrcweir         }
874cdf0e10cSrcweir     }
875cdf0e10cSrcweir 
876cdf0e10cSrcweir     return nodeMatch;
877cdf0e10cSrcweir }
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 
880cdf0e10cSrcweir css::uno::Reference<css::xml::dom::XNode>
881cdf0e10cSrcweir DescriptionInfoset::matchLanguage(
882cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
883cdf0e10cSrcweir {
884cdf0e10cSrcweir     OSL_ASSERT(xParent.is());
885cdf0e10cSrcweir     css::uno::Reference<css::xml::dom::XNode> nodeMatch;
886cdf0e10cSrcweir 
887cdf0e10cSrcweir     //first try exact match for lang
888cdf0e10cSrcweir     const ::rtl::OUString exp1(
889cdf0e10cSrcweir         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
890cdf0e10cSrcweir         + officeLocale.Language
891cdf0e10cSrcweir         + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
892cdf0e10cSrcweir     try {
893cdf0e10cSrcweir         nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
894cdf0e10cSrcweir     } catch (css::xml::xpath::XPathException &) {
895cdf0e10cSrcweir         // ignore
896cdf0e10cSrcweir     }
897cdf0e10cSrcweir 
898cdf0e10cSrcweir     //try to match in strings that also have a country and/orvariant, for example en  matches in
899cdf0e10cSrcweir     //en-US-montana, en-US, en-montana
900cdf0e10cSrcweir     if (!nodeMatch.is())
901cdf0e10cSrcweir     {
902cdf0e10cSrcweir         const ::rtl::OUString exp2(
903cdf0e10cSrcweir             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
904cdf0e10cSrcweir             + officeLocale.Language
905cdf0e10cSrcweir             + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
906cdf0e10cSrcweir         try {
907cdf0e10cSrcweir             nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
908cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
909cdf0e10cSrcweir             // ignore
910cdf0e10cSrcweir         }
911cdf0e10cSrcweir     }
912cdf0e10cSrcweir     return nodeMatch;
913cdf0e10cSrcweir }
914cdf0e10cSrcweir 
915cdf0e10cSrcweir css::uno::Reference<css::xml::dom::XNode>
916cdf0e10cSrcweir DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference< css::xml::dom::XNode >
917cdf0e10cSrcweir                                     const & xParent) const
918cdf0e10cSrcweir {
919cdf0e10cSrcweir     OSL_ASSERT(xParent.is());
920cdf0e10cSrcweir     if (xParent->getNodeName().equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple-license"))))
921cdf0e10cSrcweir     {
922cdf0e10cSrcweir         css::uno::Reference<css::xml::dom::XNode> nodeDefault;
923cdf0e10cSrcweir         try {
924cdf0e10cSrcweir             nodeDefault = m_xpath->selectSingleNode(xParent, ::rtl::OUString(
925cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("@default-license-id")));
926cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
927cdf0e10cSrcweir             // ignore
928cdf0e10cSrcweir         }
929cdf0e10cSrcweir         if (nodeDefault.is())
930cdf0e10cSrcweir         {
931cdf0e10cSrcweir             //The old way
932cdf0e10cSrcweir             const ::rtl::OUString exp1(
933cdf0e10cSrcweir                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \""))
934cdf0e10cSrcweir                 + nodeDefault->getNodeValue()
935cdf0e10cSrcweir                 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
936cdf0e10cSrcweir             try {
937cdf0e10cSrcweir                 return m_xpath->selectSingleNode(xParent, exp1);
938cdf0e10cSrcweir             } catch (css::xml::xpath::XPathException &) {
939cdf0e10cSrcweir                 // ignore
940cdf0e10cSrcweir             }
941cdf0e10cSrcweir         }
942cdf0e10cSrcweir     }
943cdf0e10cSrcweir 
944cdf0e10cSrcweir     const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]"));
945cdf0e10cSrcweir     try {
946cdf0e10cSrcweir         return m_xpath->selectSingleNode(xParent, exp2);
947cdf0e10cSrcweir     } catch (css::xml::xpath::XPathException &) {
948cdf0e10cSrcweir         // ignore
949cdf0e10cSrcweir         return 0;
950cdf0e10cSrcweir     }
951cdf0e10cSrcweir }
952cdf0e10cSrcweir 
953cdf0e10cSrcweir ::rtl::OUString DescriptionInfoset::getLocalizedHREFAttrFromChild(
954cdf0e10cSrcweir     ::rtl::OUString const & sXPathParent, bool * out_bParentExists)
955cdf0e10cSrcweir     const
956cdf0e10cSrcweir {
957cdf0e10cSrcweir     css::uno::Reference< css::xml::dom::XNode > node =
958cdf0e10cSrcweir         getLocalizedChild(sXPathParent);
959cdf0e10cSrcweir 
960cdf0e10cSrcweir     ::rtl::OUString sURL;
961cdf0e10cSrcweir     if (node.is())
962cdf0e10cSrcweir     {
963cdf0e10cSrcweir         if (out_bParentExists)
964cdf0e10cSrcweir             *out_bParentExists = true;
965cdf0e10cSrcweir         const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
966cdf0e10cSrcweir         css::uno::Reference< css::xml::dom::XNode > xURL;
967cdf0e10cSrcweir         try {
968cdf0e10cSrcweir             xURL = m_xpath->selectSingleNode(node, exp);
969cdf0e10cSrcweir         } catch (css::xml::xpath::XPathException &) {
970cdf0e10cSrcweir             // ignore
971cdf0e10cSrcweir         }
972cdf0e10cSrcweir         OSL_ASSERT(xURL.is());
973cdf0e10cSrcweir         if (xURL.is())
974cdf0e10cSrcweir             sURL = xURL->getNodeValue();
975cdf0e10cSrcweir     }
976cdf0e10cSrcweir     else
977cdf0e10cSrcweir     {
978cdf0e10cSrcweir         if (out_bParentExists)
979cdf0e10cSrcweir             *out_bParentExists = false;
980cdf0e10cSrcweir     }
981cdf0e10cSrcweir     return sURL;
982cdf0e10cSrcweir }
983cdf0e10cSrcweir 
984cdf0e10cSrcweir }
985