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