Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <config_folders.h>
21 :
22 : #include <cppuhelper/implbase1.hxx>
23 : #include <cppuhelper/implbase3.hxx>
24 : #include <cppuhelper/implementationentry.hxx>
25 : #include <cppuhelper/supportsservice.hxx>
26 : #include <com/sun/star/beans/Property.hpp>
27 : #include <com/sun/star/beans/PropertyValue.hpp>
28 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
29 : #include <com/sun/star/beans/NamedValue.hpp>
30 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
31 : #include <com/sun/star/container/XNameAccess.hpp>
32 : #include <com/sun/star/deployment/UpdateInformationEntry.hpp>
33 : #include <com/sun/star/deployment/UpdateInformationProvider.hpp>
34 : #include <com/sun/star/io/XActiveDataSink.hpp>
35 : #include <com/sun/star/io/XInputStream.hpp>
36 : #include <com/sun/star/lang/XComponent.hpp>
37 : #include <com/sun/star/lang/XServiceInfo.hpp>
38 : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
39 : #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
40 : #include <com/sun/star/ucb/XCommandProcessor2.hpp>
41 : #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
42 : #include <com/sun/star/ucb/XContentProvider.hpp>
43 : #include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
44 : #include <com/sun/star/ucb/OpenCommandArgument3.hpp>
45 : #include <com/sun/star/ucb/OpenMode.hpp>
46 : #include <com/sun/star/sdbc/XRow.hpp>
47 : #include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
48 : #include <com/sun/star/xml/dom/DocumentBuilder.hpp>
49 : #include <com/sun/star/xml/xpath/XPathAPI.hpp>
50 :
51 : #include <rtl/ref.hxx>
52 : #include <rtl/bootstrap.hxx>
53 : #include <rtl/ustrbuf.hxx>
54 : #include <sal/log.hxx>
55 : #include <osl/diagnose.h>
56 : #include <osl/process.h>
57 : #include <osl/conditn.hxx>
58 :
59 : namespace beans = com::sun::star::beans ;
60 : namespace container = com::sun::star::container ;
61 : namespace deployment = com::sun::star::deployment ;
62 : namespace io = com::sun::star::io ;
63 : namespace lang = com::sun::star::lang ;
64 : namespace task = com::sun::star::task ;
65 : namespace ucb = com::sun::star::ucb ;
66 : namespace uno = com::sun::star::uno ;
67 : namespace xml = com::sun::star::xml ;
68 : namespace sdbc = com::sun::star::sdbc ;
69 :
70 :
71 :
72 :
73 : namespace
74 : {
75 :
76 : #ifdef DEBUG
77 :
78 : class InputStreamWrapper : public ::cppu::WeakImplHelper1< io::XInputStream >
79 : {
80 : uno::Reference< io::XInputStream > m_xStream;
81 :
82 : public:
83 : InputStreamWrapper(const uno::Reference< io::XInputStream >& rxStream) :
84 : m_xStream(rxStream) {};
85 :
86 : virtual sal_Int32 SAL_CALL readBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
87 : throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
88 : {
89 : sal_Int32 n = m_xStream->readBytes(aData, nBytesToRead);
90 : if ( n )
91 : OSL_TRACE( "Read [%d] bytes: %s", n, aData.get()->elements );
92 : return n;
93 : };
94 : virtual sal_Int32 SAL_CALL readSomeBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
95 : throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
96 : {
97 : sal_Int32 n = m_xStream->readSomeBytes(aData, nMaxBytesToRead);
98 : if ( n )
99 : OSL_TRACE( "Read [%d] bytes: %s", n, aData.get()->elements );
100 : return n;
101 : };
102 : virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
103 : throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
104 : { m_xStream->skipBytes(nBytesToSkip); };
105 : virtual sal_Int32 SAL_CALL available()
106 : throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
107 : { return m_xStream->available(); };
108 : virtual void SAL_CALL closeInput( )
109 : throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
110 : {};
111 : };
112 :
113 : #define INPUT_STREAM(i) new InputStreamWrapper(i)
114 : #else
115 : #define INPUT_STREAM(i) i
116 : #endif
117 :
118 :
119 :
120 0 : class ActiveDataSink : public ::cppu::WeakImplHelper1< io::XActiveDataSink >
121 : {
122 : uno::Reference< io::XInputStream > m_xStream;
123 :
124 : public:
125 0 : ActiveDataSink() {};
126 :
127 0 : virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream()
128 0 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return m_xStream; };
129 0 : virtual void SAL_CALL setInputStream( uno::Reference< io::XInputStream > const & rStream )
130 0 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { m_xStream = rStream; };
131 : };
132 :
133 :
134 :
135 : class UpdateInformationProvider :
136 : public ::cppu::WeakImplHelper3< deployment::XUpdateInformationProvider,
137 : ucb::XWebDAVCommandEnvironment,
138 : lang::XServiceInfo >
139 : {
140 : public:
141 : static uno::Reference< uno::XInterface > createInstance(const uno::Reference<uno::XComponentContext>& xContext);
142 :
143 : static uno::Sequence< OUString > getServiceNames();
144 : static OUString getImplName();
145 :
146 : uno::Reference< xml::dom::XElement > getDocumentRoot(const uno::Reference< xml::dom::XNode >& rxNode);
147 : uno::Reference< xml::dom::XNode > getChildNode(const uno::Reference< xml::dom::XNode >& rxNode, const OUString& rName);
148 :
149 :
150 : // XUpdateInformationService
151 : virtual uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
152 : getUpdateInformation(
153 : uno::Sequence< OUString > const & repositories,
154 : OUString const & extensionId
155 : ) throw (uno::Exception, uno::RuntimeException, std::exception) SAL_OVERRIDE;
156 :
157 : virtual void SAL_CALL cancel()
158 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
159 :
160 : virtual void SAL_CALL setInteractionHandler(
161 : uno::Reference< task::XInteractionHandler > const & handler )
162 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
163 :
164 : virtual uno::Reference< container::XEnumeration > SAL_CALL
165 : getUpdateInformationEnumeration(
166 : uno::Sequence< OUString > const & repositories,
167 : OUString const & extensionId
168 : ) throw (uno::Exception, uno::RuntimeException, std::exception) SAL_OVERRIDE;
169 :
170 : // XCommandEnvironment
171 : virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler()
172 : throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
173 :
174 0 : virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler()
175 0 : throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE { return uno::Reference< ucb::XProgressHandler >(); };
176 :
177 : // XWebDAVCommandEnvironment
178 0 : virtual uno::Sequence< beans::StringPair > SAL_CALL getUserRequestHeaders(
179 : const OUString&, ucb::WebDAVHTTPMethod )
180 0 : throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE { return m_aRequestHeaderList; };
181 :
182 : // XServiceInfo
183 : virtual OUString SAL_CALL getImplementationName()
184 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
185 : virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName)
186 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
187 : virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
188 : throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
189 :
190 : protected:
191 :
192 : virtual ~UpdateInformationProvider();
193 : static OUString getConfigurationItem(uno::Reference<lang::XMultiServiceFactory> const & configurationProvider, OUString const & node, OUString const & item);
194 :
195 : private:
196 : uno::Reference< io::XInputStream > load(const OUString& rURL);
197 :
198 : void storeCommandInfo( sal_Int32 nCommandId,
199 : uno::Reference< ucb::XCommandProcessor > const & rxCommandProcessor);
200 :
201 : UpdateInformationProvider(const uno::Reference<uno::XComponentContext>& xContext,
202 : const uno::Reference< ucb::XUniversalContentBroker >& xUniversalContentBroker,
203 : const uno::Reference< xml::dom::XDocumentBuilder >& xDocumentBuilder,
204 : const uno::Reference< xml::xpath::XXPathAPI >& xXPathAPI);
205 :
206 : const uno::Reference< uno::XComponentContext> m_xContext;
207 :
208 : const uno::Reference< ucb::XUniversalContentBroker > m_xUniversalContentBroker;
209 : const uno::Reference< xml::dom::XDocumentBuilder > m_xDocumentBuilder;
210 : const uno::Reference< xml::xpath::XXPathAPI > m_xXPathAPI;
211 :
212 : uno::Sequence< beans::StringPair > m_aRequestHeaderList;
213 :
214 : uno::Reference< ucb::XCommandProcessor > m_xCommandProcessor;
215 : uno::Reference< task::XInteractionHandler > m_xInteractionHandler;
216 : uno::Reference< task::XInteractionHandler > m_xPwContainerInteractionHandler;
217 :
218 : osl::Mutex m_aMutex;
219 : osl::Condition m_bCancelled;
220 :
221 : sal_Int32 m_nCommandId;
222 : };
223 :
224 :
225 :
226 : class UpdateInformationEnumeration : public ::cppu::WeakImplHelper1< container::XEnumeration >
227 : {
228 : public:
229 0 : UpdateInformationEnumeration(const uno::Reference< xml::dom::XNodeList >& xNodeList,
230 : const uno::Reference< UpdateInformationProvider >& xUpdateInformationProvider) :
231 : m_xUpdateInformationProvider(xUpdateInformationProvider),
232 : m_xNodeList(xNodeList),
233 0 : m_nNodes(xNodeList.is() ? xNodeList->getLength() : 0),
234 0 : m_nCount(0)
235 : {
236 0 : };
237 :
238 0 : virtual ~UpdateInformationEnumeration() {};
239 :
240 : // XEnumeration
241 0 : sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return m_nCount < m_nNodes; };
242 0 : uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
243 : {
244 : OSL_ASSERT( m_xNodeList.is() );
245 : OSL_ASSERT( m_xUpdateInformationProvider.is() );
246 :
247 0 : if( !(m_nCount < m_nNodes ) )
248 0 : throw container::NoSuchElementException(OUString::number(m_nCount), *this);
249 :
250 : try
251 : {
252 0 : deployment::UpdateInformationEntry aEntry;
253 :
254 0 : uno::Reference< xml::dom::XNode > xAtomEntryNode( m_xNodeList->item(m_nCount++) );
255 :
256 : uno::Reference< xml::dom::XNode > xSummaryNode(
257 : m_xUpdateInformationProvider->getChildNode( xAtomEntryNode, "summary/text()" )
258 0 : );
259 :
260 0 : if( xSummaryNode.is() )
261 0 : aEntry.Description = xSummaryNode->getNodeValue();
262 :
263 : uno::Reference< xml::dom::XNode > xContentNode(
264 0 : m_xUpdateInformationProvider->getChildNode( xAtomEntryNode, "content" ) );
265 :
266 0 : if( xContentNode.is() )
267 0 : aEntry.UpdateDocument = m_xUpdateInformationProvider->getDocumentRoot(xContentNode);
268 :
269 0 : return uno::makeAny(aEntry);
270 : }
271 :
272 : // action has been aborted
273 0 : catch( ucb::CommandAbortedException const & e)
274 0 : { throw lang::WrappedTargetException( "Command aborted", *this, uno::makeAny(e) ); }
275 :
276 : // let runtime exception pass
277 0 : catch( uno::RuntimeException const & ) { throw; }
278 :
279 : // document not accessible
280 0 : catch( uno::Exception const & e)
281 0 : { throw lang::WrappedTargetException( "Document not accessible", *this, uno::makeAny(e) ); }
282 : }
283 :
284 : private:
285 : const uno::Reference< UpdateInformationProvider > m_xUpdateInformationProvider;
286 : const uno::Reference< xml::dom::XNodeList > m_xNodeList;
287 : const sal_Int32 m_nNodes;
288 : sal_Int32 m_nCount;
289 : };
290 :
291 :
292 :
293 : class SingleUpdateInformationEnumeration : public ::cppu::WeakImplHelper1< container::XEnumeration >
294 : {
295 : public:
296 0 : SingleUpdateInformationEnumeration(const uno::Reference< xml::dom::XElement >& xElement)
297 0 : : m_nCount(0) { m_aEntry.UpdateDocument = xElement; };
298 0 : virtual ~SingleUpdateInformationEnumeration() {};
299 :
300 : // XEnumeration
301 0 : sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return 0 == m_nCount; };
302 0 : uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
303 : {
304 0 : if( m_nCount > 0 )
305 0 : throw container::NoSuchElementException(OUString::number(m_nCount), *this);
306 :
307 0 : ++m_nCount;
308 0 : return uno::makeAny(m_aEntry);
309 : };
310 :
311 : private:
312 : sal_Int32 m_nCount;
313 : deployment::UpdateInformationEntry m_aEntry;
314 : };
315 :
316 :
317 :
318 :
319 1 : UpdateInformationProvider::UpdateInformationProvider(
320 : const uno::Reference<uno::XComponentContext>& xContext,
321 : const uno::Reference< ucb::XUniversalContentBroker >& xUniversalContentBroker,
322 : const uno::Reference< xml::dom::XDocumentBuilder >& xDocumentBuilder,
323 : const uno::Reference< xml::xpath::XXPathAPI >& xXPathAPI)
324 : : m_xContext(xContext)
325 : , m_xUniversalContentBroker(xUniversalContentBroker)
326 : , m_xDocumentBuilder(xDocumentBuilder)
327 : , m_xXPathAPI(xXPathAPI)
328 : , m_aRequestHeaderList(1)
329 1 : , m_nCommandId(0)
330 : {
331 : uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
332 1 : com::sun::star::configuration::theDefaultProvider::get(xContext));
333 :
334 2 : OUStringBuffer buf;
335 : buf.append(
336 : getConfigurationItem(
337 : xConfigurationProvider,
338 : "org.openoffice.Setup/Product",
339 1 : "ooName"));
340 1 : buf.append(' ');
341 : buf.append(
342 : getConfigurationItem(
343 : xConfigurationProvider,
344 : "org.openoffice.Setup/Product",
345 1 : "ooSetupVersion"));
346 : OUString extension(
347 : getConfigurationItem(
348 : xConfigurationProvider,
349 : "org.openoffice.Setup/Product",
350 2 : "ooSetupExtension"));
351 1 : if (!extension.isEmpty()) {
352 1 : buf.append(extension);
353 : }
354 2 : OUString product(buf.makeStringAndClear());
355 :
356 2 : OUString aUserAgent( "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":UpdateUserAgent}" );
357 1 : rtl::Bootstrap::expandMacros( aUserAgent );
358 1 : aUserAgent = aUserAgent.replaceAll("<PRODUCT>", product);
359 : SAL_INFO("extensions.update", "UpdateUserAgent: " << aUserAgent);
360 :
361 1 : m_aRequestHeaderList[0].First = "Accept-Language";
362 1 : m_aRequestHeaderList[0].Second = getConfigurationItem( xConfigurationProvider, "org.openoffice.Setup/L10N", "ooLocale" );
363 1 : if( !aUserAgent.isEmpty() )
364 : {
365 1 : m_aRequestHeaderList.realloc(2);
366 1 : m_aRequestHeaderList[1].First = "User-Agent";
367 1 : m_aRequestHeaderList[1].Second = aUserAgent;
368 1 : }
369 1 : }
370 :
371 :
372 : uno::Reference< uno::XInterface >
373 1 : UpdateInformationProvider::createInstance(const uno::Reference<uno::XComponentContext>& xContext)
374 : {
375 : uno::Reference< ucb::XUniversalContentBroker > xUniversalContentBroker =
376 1 : ucb::UniversalContentBroker::create(xContext);
377 :
378 : uno::Reference< xml::dom::XDocumentBuilder > xDocumentBuilder(
379 2 : xml::dom::DocumentBuilder::create(xContext));
380 :
381 2 : uno::Reference< xml::xpath::XXPathAPI > xXPath = xml::xpath::XPathAPI::create( xContext );
382 :
383 1 : xXPath->registerNS( "atom", "http://www.w3.org/2005/Atom" );
384 :
385 2 : return *new UpdateInformationProvider(xContext, xUniversalContentBroker, xDocumentBuilder, xXPath);
386 : }
387 :
388 :
389 :
390 2 : UpdateInformationProvider::~UpdateInformationProvider()
391 : {
392 2 : }
393 :
394 :
395 :
396 : OUString
397 4 : UpdateInformationProvider::getConfigurationItem(uno::Reference<lang::XMultiServiceFactory> const & configurationProvider, OUString const & node, OUString const & item)
398 : {
399 4 : rtl::OUString sRet;
400 8 : beans::PropertyValue aProperty;
401 4 : aProperty.Name = "nodepath";
402 4 : aProperty.Value = uno::makeAny(node);
403 :
404 8 : uno::Sequence< uno::Any > aArgumentList( 1 );
405 4 : aArgumentList[0] = uno::makeAny( aProperty );
406 :
407 : uno::Reference< container::XNameAccess > xNameAccess(
408 4 : configurationProvider->createInstanceWithArguments(
409 : "com.sun.star.configuration.ConfigurationAccess",
410 4 : aArgumentList ),
411 8 : uno::UNO_QUERY_THROW);
412 :
413 4 : xNameAccess->getByName(item) >>= sRet;
414 8 : return sRet;
415 : }
416 :
417 :
418 :
419 : void
420 0 : UpdateInformationProvider::storeCommandInfo(
421 : sal_Int32 nCommandId,
422 : uno::Reference< ucb::XCommandProcessor > const & rxCommandProcessor)
423 : {
424 0 : osl::MutexGuard aGuard(m_aMutex);
425 :
426 0 : m_nCommandId = nCommandId;
427 0 : m_xCommandProcessor = rxCommandProcessor;
428 0 : }
429 :
430 :
431 :
432 : uno::Reference< io::XInputStream >
433 0 : UpdateInformationProvider::load(const OUString& rURL)
434 : {
435 0 : uno::Reference< ucb::XContentIdentifier > xId = m_xUniversalContentBroker->createContentIdentifier(rURL);
436 :
437 0 : if( !xId.is() )
438 : throw uno::RuntimeException(
439 0 : "unable to obtain universal content id", *this);
440 :
441 0 : uno::Reference< ucb::XCommandProcessor > xCommandProcessor(m_xUniversalContentBroker->queryContent(xId), uno::UNO_QUERY_THROW);
442 0 : rtl::Reference< ActiveDataSink > aSink(new ActiveDataSink());
443 :
444 : // Disable KeepAlive in webdav - don't want millions of office
445 : // instances phone home & clog up servers
446 0 : uno::Sequence< beans::NamedValue > aProps( 1 );
447 0 : aProps[ 0 ] = beans::NamedValue(
448 0 : "KeepAlive", uno::makeAny(sal_False));
449 :
450 0 : ucb::OpenCommandArgument3 aOpenArgument;
451 0 : aOpenArgument.Mode = ucb::OpenMode::DOCUMENT;
452 0 : aOpenArgument.Priority = 32768;
453 0 : aOpenArgument.Sink = *aSink;
454 0 : aOpenArgument.OpeningFlags = aProps;
455 :
456 0 : ucb::Command aCommand;
457 0 : aCommand.Name = "open";
458 0 : aCommand.Argument = uno::makeAny(aOpenArgument);
459 :
460 0 : sal_Int32 nCommandId = xCommandProcessor->createCommandIdentifier();
461 :
462 0 : storeCommandInfo(nCommandId, xCommandProcessor);
463 : try
464 : {
465 0 : xCommandProcessor->execute(aCommand, nCommandId,
466 0 : static_cast < XCommandEnvironment *> (this));
467 : }
468 0 : catch( const uno::Exception & /* e */ )
469 : {
470 0 : storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
471 :
472 0 : uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
473 0 : if( xCommandProcessor2.is() )
474 0 : xCommandProcessor2->releaseCommandIdentifier(nCommandId);
475 :
476 0 : throw;
477 : }
478 0 : storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
479 :
480 0 : uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
481 0 : if( xCommandProcessor2.is() )
482 0 : xCommandProcessor2->releaseCommandIdentifier(nCommandId);
483 :
484 0 : return INPUT_STREAM(aSink->getInputStream());
485 : }
486 :
487 :
488 :
489 : // TODO: docu content node
490 :
491 : uno::Reference< xml::dom::XElement >
492 0 : UpdateInformationProvider::getDocumentRoot(const uno::Reference< xml::dom::XNode >& rxNode)
493 : {
494 : OSL_ASSERT(m_xDocumentBuilder.is());
495 :
496 0 : uno::Reference< xml::dom::XElement > xElement(rxNode, uno::UNO_QUERY_THROW);
497 :
498 : // load the document referenced in 'src' attribute ..
499 0 : if( xElement->hasAttribute( "src" ) )
500 : {
501 : uno::Reference< xml::dom::XDocument > xUpdateXML =
502 0 : m_xDocumentBuilder->parse(load(xElement->getAttribute( "src" )));
503 :
504 : OSL_ASSERT( xUpdateXML.is() );
505 :
506 0 : if( xUpdateXML.is() )
507 0 : return xUpdateXML->getDocumentElement();
508 : }
509 : // .. or return the (single) child element
510 : else
511 : {
512 0 : uno::Reference< xml::dom::XNodeList> xChildNodes = rxNode->getChildNodes();
513 :
514 : // ignore possible #text nodes
515 0 : sal_Int32 nmax = xChildNodes->getLength();
516 0 : for(sal_Int32 n=0; n < nmax; n++)
517 : {
518 0 : uno::Reference< xml::dom::XElement > xChildElement(xChildNodes->item(n), uno::UNO_QUERY);
519 0 : if( xChildElement.is() )
520 : {
521 : /* Copy the content to a dedicated document since XXPathAPI->selectNodeList
522 : * seems to evaluate expression always relative to the root node.
523 : */
524 0 : uno::Reference< xml::dom::XDocument > xUpdateXML = m_xDocumentBuilder->newDocument();
525 0 : xUpdateXML->appendChild( xUpdateXML->importNode(xChildElement.get(), sal_True ) );
526 0 : return xUpdateXML->getDocumentElement();
527 : }
528 0 : }
529 : }
530 :
531 0 : return uno::Reference< xml::dom::XElement > ();
532 : }
533 :
534 :
535 :
536 : uno::Reference< xml::dom::XNode >
537 0 : UpdateInformationProvider::getChildNode(const uno::Reference< xml::dom::XNode >& rxNode,
538 : const OUString& rName)
539 : {
540 : OSL_ASSERT(m_xXPathAPI.is());
541 : try {
542 0 : return m_xXPathAPI->selectSingleNode(rxNode, "./atom:" + rName);
543 0 : } catch (const xml::xpath::XPathException &) {
544 : // ignore
545 0 : return 0;
546 : }
547 : }
548 :
549 :
550 :
551 : uno::Reference< container::XEnumeration > SAL_CALL
552 0 : UpdateInformationProvider::getUpdateInformationEnumeration(
553 : uno::Sequence< OUString > const & repositories,
554 : OUString const & extensionId
555 : ) throw (uno::Exception, uno::RuntimeException, std::exception)
556 : {
557 : OSL_ASSERT(m_xDocumentBuilder.is());
558 :
559 : // reset cancelled flag
560 0 : m_bCancelled.reset();
561 :
562 0 : for(sal_Int32 n=0; n<repositories.getLength(); n++)
563 : {
564 : try
565 : {
566 0 : uno::Reference< xml::dom::XDocument > xDocument = m_xDocumentBuilder->parse(load(repositories[n]));
567 0 : uno::Reference< xml::dom::XElement > xElement;
568 :
569 0 : if( xDocument.is() )
570 0 : xElement = xDocument->getDocumentElement();
571 :
572 0 : if( xElement.is() )
573 : {
574 0 : if( xElement->getNodeName() == "feed" )
575 : {
576 0 : OUString aXPathExpression;
577 :
578 0 : if( !extensionId.isEmpty() )
579 0 : aXPathExpression = "//atom:entry/atom:category[@term=\'" + extensionId + "\']/..";
580 : else
581 0 : aXPathExpression = "//atom:entry";
582 :
583 0 : uno::Reference< xml::dom::XNodeList > xNodeList;
584 : try {
585 0 : xNodeList = m_xXPathAPI->selectNodeList(xDocument.get(),
586 0 : aXPathExpression);
587 0 : } catch (const xml::xpath::XPathException &) {
588 : // ignore
589 : }
590 :
591 0 : return new UpdateInformationEnumeration(xNodeList, this);
592 : }
593 : else
594 : {
595 0 : return new SingleUpdateInformationEnumeration(xElement);
596 : }
597 : }
598 :
599 0 : if( m_bCancelled.check() )
600 0 : break;
601 : }
602 0 : catch( uno::RuntimeException const& /*e*/)
603 : {
604 : // #i118675# ignore runtime exceptions for now
605 : // especially the "unsatisfied query for interface of
606 : // type com.sun.star.ucb.XCommandProcessor!" exception
607 : }
608 :
609 : // rethrow only if last url in the list
610 0 : catch( uno::Exception const & )
611 : {
612 0 : if( n+1 >= repositories.getLength() )
613 0 : throw;
614 : }
615 : }
616 :
617 0 : return uno::Reference< container::XEnumeration >();
618 : }
619 :
620 :
621 :
622 : uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
623 0 : UpdateInformationProvider::getUpdateInformation(
624 : uno::Sequence< OUString > const & repositories,
625 : OUString const & extensionId
626 : ) throw (uno::Exception, uno::RuntimeException, std::exception)
627 : {
628 : uno::Reference< container::XEnumeration > xEnumeration(
629 0 : getUpdateInformationEnumeration(repositories, extensionId)
630 0 : );
631 :
632 0 : uno::Sequence< uno::Reference< xml::dom::XElement > > aRet;
633 :
634 0 : if( xEnumeration.is() )
635 : {
636 0 : while( xEnumeration->hasMoreElements() )
637 : {
638 : try
639 : {
640 0 : deployment::UpdateInformationEntry aEntry;
641 0 : if( (xEnumeration->nextElement() >>= aEntry ) && aEntry.UpdateDocument.is() )
642 : {
643 0 : sal_Int32 n = aRet.getLength();
644 0 : aRet.realloc(n + 1);
645 0 : aRet[n] = aEntry.UpdateDocument;
646 0 : }
647 : }
648 :
649 0 : catch( const lang::WrappedTargetException& e )
650 : {
651 : // command aborted, return what we have got so far
652 0 : if( e.TargetException.isExtractableTo( ::cppu::UnoType< ::com::sun::star::ucb::CommandAbortedException >::get() ) )
653 : {
654 0 : break;
655 : }
656 :
657 : // ignore files that can't be loaded
658 0 : }
659 : }
660 : }
661 :
662 0 : return aRet;
663 : }
664 :
665 :
666 :
667 : void SAL_CALL
668 0 : UpdateInformationProvider::cancel() throw (uno::RuntimeException, std::exception)
669 : {
670 0 : m_bCancelled.set();
671 :
672 0 : osl::MutexGuard aGuard(m_aMutex);
673 0 : if( m_xCommandProcessor.is() )
674 0 : m_xCommandProcessor->abort(m_nCommandId);
675 0 : }
676 :
677 :
678 :
679 : void SAL_CALL
680 0 : UpdateInformationProvider::setInteractionHandler(
681 : uno::Reference< task::XInteractionHandler > const & handler )
682 : throw (uno::RuntimeException, std::exception)
683 : {
684 0 : osl::MutexGuard aGuard(m_aMutex);
685 0 : m_xInteractionHandler = handler;
686 0 : }
687 :
688 :
689 :
690 : uno::Reference< task::XInteractionHandler > SAL_CALL
691 0 : UpdateInformationProvider::getInteractionHandler()
692 : throw ( uno::RuntimeException, std::exception )
693 : {
694 0 : osl::MutexGuard aGuard( m_aMutex );
695 :
696 0 : if ( m_xInteractionHandler.is() )
697 0 : return m_xInteractionHandler;
698 : else
699 : {
700 : try
701 : {
702 : // Supply an interaction handler that uses the password container
703 : // service to obtain credentials without displaying a password gui.
704 :
705 0 : if ( !m_xPwContainerInteractionHandler.is() )
706 : m_xPwContainerInteractionHandler
707 0 : = task::PasswordContainerInteractionHandler::create(
708 0 : m_xContext );
709 : }
710 0 : catch ( uno::RuntimeException const & )
711 : {
712 0 : throw;
713 : }
714 0 : catch ( uno::Exception const & )
715 : {
716 : }
717 0 : return m_xPwContainerInteractionHandler;
718 0 : }
719 : }
720 :
721 :
722 : uno::Sequence< OUString >
723 2 : UpdateInformationProvider::getServiceNames()
724 : {
725 2 : uno::Sequence< OUString > aServiceList(1);
726 2 : aServiceList[0] = "com.sun.star.deployment.UpdateInformationProvider";
727 2 : return aServiceList;
728 : };
729 :
730 :
731 :
732 : OUString
733 2 : UpdateInformationProvider::getImplName()
734 : {
735 2 : return OUString("vnd.sun.UpdateInformationProvider");
736 : }
737 :
738 :
739 :
740 : OUString SAL_CALL
741 1 : UpdateInformationProvider::getImplementationName() throw (uno::RuntimeException, std::exception)
742 : {
743 1 : return getImplName();
744 : }
745 :
746 :
747 :
748 : uno::Sequence< OUString > SAL_CALL
749 1 : UpdateInformationProvider::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
750 : {
751 1 : return getServiceNames();
752 : }
753 :
754 : sal_Bool SAL_CALL
755 0 : UpdateInformationProvider::supportsService( OUString const & serviceName ) throw (uno::RuntimeException, std::exception)
756 : {
757 0 : return cppu::supportsService(this, serviceName);
758 : }
759 :
760 : } // anonymous namespace
761 :
762 :
763 :
764 : static uno::Reference<uno::XInterface> SAL_CALL
765 1 : createInstance(uno::Reference<uno::XComponentContext> const & xContext)
766 : {
767 1 : return UpdateInformationProvider::createInstance(xContext);
768 : }
769 :
770 :
771 :
772 : static const cppu::ImplementationEntry kImplementations_entries[] =
773 : {
774 : {
775 : createInstance,
776 : UpdateInformationProvider::getImplName,
777 : UpdateInformationProvider::getServiceNames,
778 : cppu::createSingleComponentFactory,
779 : NULL,
780 : 0
781 : },
782 : { NULL, NULL, NULL, NULL, NULL, 0 }
783 : } ;
784 :
785 :
786 :
787 1 : extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL updatefeed_component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
788 : {
789 : return cppu::component_getFactoryHelper(
790 : pszImplementationName,
791 : pServiceManager,
792 : pRegistryKey,
793 1 : kImplementations_entries) ;
794 : }
795 :
796 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|