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 :
21 : #include <cppuhelper/implbase1.hxx>
22 : #include <cppuhelper/implbase4.hxx>
23 : #include <cppuhelper/implementationentry.hxx>
24 : #include <com/sun/star/beans/Property.hpp>
25 : #include <com/sun/star/beans/PropertyValue.hpp>
26 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
27 : #include <com/sun/star/beans/NamedValue.hpp>
28 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
29 : #include <com/sun/star/container/XNameAccess.hpp>
30 : #include <com/sun/star/deployment/UpdateInformationEntry.hpp>
31 : #include <com/sun/star/deployment/UpdateInformationProvider.hpp>
32 : #include <com/sun/star/io/XActiveDataSink.hpp>
33 : #include <com/sun/star/io/XInputStream.hpp>
34 : #include <com/sun/star/lang/XComponent.hpp>
35 : #include <com/sun/star/lang/XServiceInfo.hpp>
36 : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
37 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
38 : #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
39 : #include <com/sun/star/ucb/XCommandProcessor2.hpp>
40 : #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
41 : #include <com/sun/star/ucb/XContentProvider.hpp>
42 : #include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
43 : #include <com/sun/star/ucb/OpenCommandArgument3.hpp>
44 : #include <com/sun/star/ucb/OpenMode.hpp>
45 : #include <com/sun/star/sdbc/XRow.hpp>
46 : #include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
47 : #include <com/sun/star/xml/dom/DocumentBuilder.hpp>
48 : #include <com/sun/star/xml/xpath/XPathAPI.hpp>
49 :
50 : #include <rtl/ref.hxx>
51 : #include <rtl/bootstrap.hxx>
52 : #include <rtl/ustrbuf.hxx>
53 : #include <osl/process.h>
54 : #include <osl/conditn.hxx>
55 :
56 : namespace beans = com::sun::star::beans ;
57 : namespace container = com::sun::star::container ;
58 : namespace deployment = com::sun::star::deployment ;
59 : namespace io = com::sun::star::io ;
60 : namespace lang = com::sun::star::lang ;
61 : namespace task = com::sun::star::task ;
62 : namespace ucb = com::sun::star::ucb ;
63 : namespace uno = com::sun::star::uno ;
64 : namespace xml = com::sun::star::xml ;
65 : namespace sdbc = com::sun::star::sdbc ;
66 :
67 :
68 : //------------------------------------------------------------------------------
69 :
70 : namespace
71 : {
72 :
73 : #ifdef DEBUG
74 :
75 : class InputStreamWrapper : public ::cppu::WeakImplHelper1< io::XInputStream >
76 : {
77 : uno::Reference< io::XInputStream > m_xStream;
78 :
79 : public:
80 : InputStreamWrapper(const uno::Reference< io::XInputStream >& rxStream) :
81 : m_xStream(rxStream) {};
82 :
83 : virtual sal_Int32 SAL_CALL readBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
84 : throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
85 : {
86 : sal_Int32 n = m_xStream->readBytes(aData, nBytesToRead);
87 : if ( n )
88 : OSL_TRACE( "Read [%d] bytes: %s", n, aData.get()->elements );
89 : return n;
90 : };
91 : virtual sal_Int32 SAL_CALL readSomeBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
92 : throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
93 : {
94 : sal_Int32 n = m_xStream->readSomeBytes(aData, nMaxBytesToRead);
95 : if ( n )
96 : OSL_TRACE( "Read [%d] bytes: %s", n, aData.get()->elements );
97 : return n;
98 : };
99 : virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
100 : throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
101 : { m_xStream->skipBytes(nBytesToSkip); };
102 : virtual sal_Int32 SAL_CALL available()
103 : throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
104 : { return m_xStream->available(); };
105 : virtual void SAL_CALL closeInput( )
106 : throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
107 : {};
108 : };
109 :
110 : #define INPUT_STREAM(i) new InputStreamWrapper(i)
111 : #else
112 : #define INPUT_STREAM(i) i
113 : #endif
114 :
115 : //------------------------------------------------------------------------------
116 :
117 0 : class ActiveDataSink : public ::cppu::WeakImplHelper1< io::XActiveDataSink >
118 : {
119 : uno::Reference< io::XInputStream > m_xStream;
120 :
121 : public:
122 0 : ActiveDataSink() {};
123 :
124 : inline operator uno::Reference< io::XActiveDataSink > () { return this; };
125 :
126 0 : virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream()
127 0 : throw (uno::RuntimeException) { return m_xStream; };
128 0 : virtual void SAL_CALL setInputStream( uno::Reference< io::XInputStream > const & rStream )
129 0 : throw (uno::RuntimeException) { m_xStream = rStream; };
130 : };
131 :
132 : //------------------------------------------------------------------------------
133 :
134 : class UpdateInformationProvider :
135 : public ::cppu::WeakImplHelper4< deployment::XUpdateInformationProvider,
136 : ucb::XCommandEnvironment,
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);
156 :
157 : virtual void SAL_CALL cancel()
158 : throw (uno::RuntimeException);
159 :
160 : virtual void SAL_CALL setInteractionHandler(
161 : uno::Reference< task::XInteractionHandler > const & handler )
162 : throw (uno::RuntimeException);
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);
169 :
170 : // XCommandEnvironment
171 : virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler()
172 : throw ( uno::RuntimeException );
173 :
174 0 : virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler()
175 0 : throw ( uno::RuntimeException ) { return uno::Reference< ucb::XProgressHandler >(); };
176 :
177 : // XWebDAVCommandEnvironment
178 0 : virtual uno::Sequence< beans::NamedValue > SAL_CALL getUserRequestHeaders(
179 : const OUString&, const OUString& )
180 0 : throw ( uno::RuntimeException ) { return m_aRequestHeaderList; };
181 :
182 : // XServiceInfo
183 : virtual OUString SAL_CALL getImplementationName()
184 : throw (uno::RuntimeException);
185 : virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName)
186 : throw (uno::RuntimeException);
187 : virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
188 : throw (uno::RuntimeException);
189 :
190 : protected:
191 :
192 : virtual ~UpdateInformationProvider();
193 : static uno::Any 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::NamedValue > 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) { return m_nCount < m_nNodes; };
242 0 : uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
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::valueOf(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) { return 0 == m_nCount; };
302 0 : uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
303 : {
304 0 : if( m_nCount > 0 )
305 0 : throw container::NoSuchElementException(OUString::valueOf(m_nCount), *this);
306 :
307 0 : ++m_nCount;
308 0 : return uno::makeAny(m_aEntry);
309 : };
310 :
311 : private:
312 : sal_uInt8 m_nCount;
313 : deployment::UpdateInformationEntry m_aEntry;
314 : };
315 :
316 :
317 : //------------------------------------------------------------------------------
318 :
319 0 : 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), m_xUniversalContentBroker(xUniversalContentBroker),
325 : m_xDocumentBuilder(xDocumentBuilder),
326 0 : m_xXPathAPI(xXPathAPI), m_aRequestHeaderList(1)
327 : {
328 : uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
329 0 : com::sun::star::configuration::theDefaultProvider::get(xContext));
330 :
331 0 : OUStringBuffer buf;
332 0 : OUString name;
333 : getConfigurationItem(
334 : xConfigurationProvider,
335 : "org.openoffice.Setup/Product",
336 0 : "ooName") >>= name;
337 0 : buf.append(name);
338 0 : buf.append(sal_Unicode(' '));
339 0 : OUString version;
340 : getConfigurationItem(
341 : xConfigurationProvider,
342 : "org.openoffice.Setup/Product",
343 0 : "ooSetupVersion") >>= version;
344 0 : buf.append(version);
345 0 : OUString extension;
346 : getConfigurationItem(
347 : xConfigurationProvider,
348 : "org.openoffice.Setup/Product",
349 0 : "ooSetupExtension") >>= extension;
350 0 : if (!extension.isEmpty()) {
351 0 : buf.append(extension);
352 : }
353 0 : OUString product(buf.makeStringAndClear());
354 :
355 0 : OUString aUserAgent( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateUserAgent}" );
356 0 : rtl::Bootstrap::expandMacros( aUserAgent );
357 :
358 0 : for (sal_Int32 i = 0;;) {
359 : i = aUserAgent.indexOfAsciiL(
360 0 : RTL_CONSTASCII_STRINGPARAM("<PRODUCT>"), i);
361 0 : if (i == -1) {
362 0 : break;
363 : }
364 0 : aUserAgent = aUserAgent.replaceAt(
365 0 : i, RTL_CONSTASCII_LENGTH("<PRODUCT>"), product);
366 0 : i += product.getLength();
367 0 : }
368 :
369 : SAL_INFO("extensions.update", "UpdateUserAgent: " << aUserAgent);
370 :
371 0 : m_aRequestHeaderList[0].Name = "Accept-Language";
372 0 : m_aRequestHeaderList[0].Value = getConfigurationItem( xConfigurationProvider, "org.openoffice.Setup/L10N", "ooLocale" );
373 0 : if( !aUserAgent.isEmpty() )
374 : {
375 0 : m_aRequestHeaderList.realloc(2);
376 0 : m_aRequestHeaderList[1].Name = "User-Agent";
377 0 : m_aRequestHeaderList[1].Value = uno::makeAny(aUserAgent);
378 0 : }
379 0 : }
380 :
381 : //------------------------------------------------------------------------------
382 : uno::Reference< uno::XInterface >
383 0 : UpdateInformationProvider::createInstance(const uno::Reference<uno::XComponentContext>& xContext)
384 : {
385 : uno::Reference< ucb::XUniversalContentBroker > xUniversalContentBroker =
386 0 : ucb::UniversalContentBroker::create(xContext);
387 :
388 : uno::Reference< xml::dom::XDocumentBuilder > xDocumentBuilder(
389 0 : xml::dom::DocumentBuilder::create(xContext));
390 :
391 0 : uno::Reference< xml::xpath::XXPathAPI > xXPath = xml::xpath::XPathAPI::create( xContext );
392 :
393 0 : xXPath->registerNS( "atom", "http://www.w3.org/2005/Atom" );
394 :
395 0 : return *new UpdateInformationProvider(xContext, xUniversalContentBroker, xDocumentBuilder, xXPath);
396 : }
397 :
398 : //------------------------------------------------------------------------------
399 :
400 0 : UpdateInformationProvider::~UpdateInformationProvider()
401 : {
402 0 : }
403 :
404 : //------------------------------------------------------------------------------
405 :
406 : uno::Any
407 0 : UpdateInformationProvider::getConfigurationItem(uno::Reference<lang::XMultiServiceFactory> const & configurationProvider, OUString const & node, OUString const & item)
408 : {
409 0 : beans::NamedValue aProperty;
410 0 : aProperty.Name = "nodepath";
411 0 : aProperty.Value = uno::makeAny(node);
412 :
413 0 : uno::Sequence< uno::Any > aArgumentList( 1 );
414 0 : aArgumentList[0] = uno::makeAny( aProperty );
415 :
416 : uno::Reference< container::XNameAccess > xNameAccess(
417 0 : configurationProvider->createInstanceWithArguments(
418 : "com.sun.star.configuration.ConfigurationAccess",
419 0 : aArgumentList ),
420 0 : uno::UNO_QUERY_THROW);
421 :
422 0 : return xNameAccess->getByName(item);
423 : }
424 :
425 : //------------------------------------------------------------------------------
426 :
427 : void
428 0 : UpdateInformationProvider::storeCommandInfo(
429 : sal_Int32 nCommandId,
430 : uno::Reference< ucb::XCommandProcessor > const & rxCommandProcessor)
431 : {
432 0 : osl::MutexGuard aGuard(m_aMutex);
433 :
434 0 : m_nCommandId = nCommandId;
435 0 : m_xCommandProcessor = rxCommandProcessor;
436 0 : }
437 :
438 : //------------------------------------------------------------------------------
439 :
440 : uno::Reference< io::XInputStream >
441 0 : UpdateInformationProvider::load(const OUString& rURL)
442 : {
443 0 : uno::Reference< ucb::XContentIdentifier > xId = m_xUniversalContentBroker->createContentIdentifier(rURL);
444 :
445 0 : if( !xId.is() )
446 : throw uno::RuntimeException(
447 0 : "unable to obtain universal content id", *this);
448 :
449 0 : uno::Reference< ucb::XCommandProcessor > xCommandProcessor(m_xUniversalContentBroker->queryContent(xId), uno::UNO_QUERY_THROW);
450 0 : rtl::Reference< ActiveDataSink > aSink(new ActiveDataSink());
451 :
452 : // Disable KeepAlive in webdav - don't want millions of office
453 : // instances phone home & clog up servers
454 0 : uno::Sequence< beans::NamedValue > aProps( 1 );
455 0 : aProps[ 0 ] = beans::NamedValue(
456 0 : "KeepAlive", uno::makeAny(sal_False));
457 :
458 0 : ucb::OpenCommandArgument3 aOpenArgument;
459 0 : aOpenArgument.Mode = ucb::OpenMode::DOCUMENT;
460 0 : aOpenArgument.Priority = 32768;
461 0 : aOpenArgument.Sink = *aSink;
462 0 : aOpenArgument.OpeningFlags = aProps;
463 :
464 0 : ucb::Command aCommand;
465 0 : aCommand.Name = "open";
466 0 : aCommand.Argument = uno::makeAny(aOpenArgument);
467 :
468 0 : sal_Int32 nCommandId = xCommandProcessor->createCommandIdentifier();
469 :
470 0 : storeCommandInfo(nCommandId, xCommandProcessor);
471 : try
472 : {
473 0 : uno::Any aResult = xCommandProcessor->execute(aCommand, nCommandId,
474 0 : static_cast < XCommandEnvironment *> (this));
475 : }
476 0 : catch( const uno::Exception & /* e */ )
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 : throw;
485 : }
486 0 : storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
487 :
488 0 : uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
489 0 : if( xCommandProcessor2.is() )
490 0 : xCommandProcessor2->releaseCommandIdentifier(nCommandId);
491 :
492 0 : return INPUT_STREAM(aSink->getInputStream());
493 : }
494 :
495 : //------------------------------------------------------------------------------
496 :
497 : // TODO: docu content node
498 :
499 : uno::Reference< xml::dom::XElement >
500 0 : UpdateInformationProvider::getDocumentRoot(const uno::Reference< xml::dom::XNode >& rxNode)
501 : {
502 : OSL_ASSERT(m_xDocumentBuilder.is());
503 :
504 0 : uno::Reference< xml::dom::XElement > xElement(rxNode, uno::UNO_QUERY_THROW);
505 :
506 : // load the document referenced in 'src' attribute ..
507 0 : if( xElement->hasAttribute( "src" ) )
508 : {
509 : uno::Reference< xml::dom::XDocument > xUpdateXML =
510 0 : m_xDocumentBuilder->parse(load(xElement->getAttribute( "src" )));
511 :
512 : OSL_ASSERT( xUpdateXML.is() );
513 :
514 0 : if( xUpdateXML.is() )
515 0 : return xUpdateXML->getDocumentElement();
516 : }
517 : // .. or return the (single) child element
518 : else
519 : {
520 0 : uno::Reference< xml::dom::XNodeList> xChildNodes = rxNode->getChildNodes();
521 :
522 : // ignore possible #text nodes
523 0 : sal_Int32 nmax = xChildNodes->getLength();
524 0 : for(sal_Int32 n=0; n < nmax; n++)
525 : {
526 0 : uno::Reference< xml::dom::XElement > xChildElement(xChildNodes->item(n), uno::UNO_QUERY);
527 0 : if( xChildElement.is() )
528 : {
529 : /* Copy the content to a dedicated document since XXPathAPI->selectNodeList
530 : * seems to evaluate expression always relative to the root node.
531 : */
532 0 : uno::Reference< xml::dom::XDocument > xUpdateXML = m_xDocumentBuilder->newDocument();
533 0 : xUpdateXML->appendChild( xUpdateXML->importNode(xChildElement.get(), sal_True ) );
534 0 : return xUpdateXML->getDocumentElement();
535 : }
536 0 : }
537 : }
538 :
539 0 : return uno::Reference< xml::dom::XElement > ();
540 : }
541 :
542 : //------------------------------------------------------------------------------
543 :
544 : uno::Reference< xml::dom::XNode >
545 0 : UpdateInformationProvider::getChildNode(const uno::Reference< xml::dom::XNode >& rxNode,
546 : const OUString& rName)
547 : {
548 : OSL_ASSERT(m_xXPathAPI.is());
549 : try {
550 0 : return m_xXPathAPI->selectSingleNode(rxNode, "./atom:" + rName);
551 0 : } catch (const xml::xpath::XPathException &) {
552 : // ignore
553 0 : return 0;
554 : }
555 : }
556 :
557 : //------------------------------------------------------------------------------
558 :
559 : uno::Reference< container::XEnumeration > SAL_CALL
560 0 : UpdateInformationProvider::getUpdateInformationEnumeration(
561 : uno::Sequence< OUString > const & repositories,
562 : OUString const & extensionId
563 : ) throw (uno::Exception, uno::RuntimeException)
564 : {
565 : OSL_ASSERT(m_xDocumentBuilder.is());
566 :
567 : // reset cancelled flag
568 0 : m_bCancelled.reset();
569 :
570 0 : for(sal_Int32 n=0; n<repositories.getLength(); n++)
571 : {
572 : try
573 : {
574 0 : uno::Reference< xml::dom::XDocument > xDocument = m_xDocumentBuilder->parse(load(repositories[n]));
575 0 : uno::Reference< xml::dom::XElement > xElement;
576 :
577 0 : if( xDocument.is() )
578 0 : xElement = xDocument->getDocumentElement();
579 :
580 0 : if( xElement.is() )
581 : {
582 0 : if( xElement->getNodeName().equalsAsciiL("feed", 4) )
583 : {
584 0 : OUString aXPathExpression;
585 :
586 0 : if( !extensionId.isEmpty() )
587 0 : aXPathExpression = "//atom:entry/atom:category[@term=\'" + extensionId + "\']/..";
588 : else
589 0 : aXPathExpression = "//atom:entry";
590 :
591 0 : uno::Reference< xml::dom::XNodeList > xNodeList;
592 : try {
593 0 : xNodeList = m_xXPathAPI->selectNodeList(xDocument.get(),
594 0 : aXPathExpression);
595 0 : } catch (const xml::xpath::XPathException &) {
596 : // ignore
597 : }
598 :
599 0 : return new UpdateInformationEnumeration(xNodeList, this);
600 : }
601 : else
602 : {
603 0 : return new SingleUpdateInformationEnumeration(xElement);
604 : }
605 : }
606 :
607 0 : if( m_bCancelled.check() )
608 0 : break;
609 : }
610 0 : catch( uno::RuntimeException const& /*e*/)
611 : {
612 : // #i118675# ignore runtime exceptions for now
613 : // especially the "unsatisfied query for interface of
614 : // type com.sun.star.ucb.XCommandProcessor!" exception
615 : }
616 :
617 : // rethrow only if last url in the list
618 0 : catch( uno::Exception const & )
619 : {
620 0 : if( n+1 >= repositories.getLength() )
621 0 : throw;
622 : }
623 : }
624 :
625 0 : return uno::Reference< container::XEnumeration >();
626 : }
627 :
628 : //------------------------------------------------------------------------------
629 :
630 : uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
631 0 : UpdateInformationProvider::getUpdateInformation(
632 : uno::Sequence< OUString > const & repositories,
633 : OUString const & extensionId
634 : ) throw (uno::Exception, uno::RuntimeException)
635 : {
636 : uno::Reference< container::XEnumeration > xEnumeration(
637 0 : getUpdateInformationEnumeration(repositories, extensionId)
638 0 : );
639 :
640 0 : uno::Sequence< uno::Reference< xml::dom::XElement > > aRet;
641 :
642 0 : if( xEnumeration.is() )
643 : {
644 0 : while( xEnumeration->hasMoreElements() )
645 : {
646 : try
647 : {
648 0 : deployment::UpdateInformationEntry aEntry;
649 0 : if( (xEnumeration->nextElement() >>= aEntry ) && aEntry.UpdateDocument.is() )
650 : {
651 0 : sal_Int32 n = aRet.getLength();
652 0 : aRet.realloc(n + 1);
653 0 : aRet[n] = aEntry.UpdateDocument;
654 0 : }
655 : }
656 :
657 0 : catch( const lang::WrappedTargetException& e )
658 : {
659 : // command aborted, return what we have got so far
660 0 : if( e.TargetException.isExtractableTo( ::cppu::UnoType< ::com::sun::star::ucb::CommandAbortedException >::get() ) )
661 : {
662 0 : break;
663 : }
664 :
665 : // ignore files that can't be loaded
666 0 : }
667 : }
668 : }
669 :
670 0 : return aRet;
671 : }
672 :
673 : //------------------------------------------------------------------------------
674 :
675 : void SAL_CALL
676 0 : UpdateInformationProvider::cancel() throw (uno::RuntimeException)
677 : {
678 0 : m_bCancelled.set();
679 :
680 0 : osl::MutexGuard aGuard(m_aMutex);
681 0 : if( m_xCommandProcessor.is() )
682 0 : m_xCommandProcessor->abort(m_nCommandId);
683 0 : }
684 :
685 : //------------------------------------------------------------------------------
686 :
687 : void SAL_CALL
688 0 : UpdateInformationProvider::setInteractionHandler(
689 : uno::Reference< task::XInteractionHandler > const & handler )
690 : throw (uno::RuntimeException)
691 : {
692 0 : osl::MutexGuard aGuard(m_aMutex);
693 0 : m_xInteractionHandler = handler;
694 0 : }
695 :
696 : //------------------------------------------------------------------------------
697 :
698 : uno::Reference< task::XInteractionHandler > SAL_CALL
699 0 : UpdateInformationProvider::getInteractionHandler()
700 : throw ( uno::RuntimeException )
701 : {
702 0 : osl::MutexGuard aGuard( m_aMutex );
703 :
704 0 : if ( m_xInteractionHandler.is() )
705 0 : return m_xInteractionHandler;
706 : else
707 : {
708 : try
709 : {
710 : // Supply an interaction handler that uses the password container
711 : // service to obtain credentials without displaying a password gui.
712 :
713 0 : if ( !m_xPwContainerInteractionHandler.is() )
714 : m_xPwContainerInteractionHandler
715 0 : = task::PasswordContainerInteractionHandler::create(
716 0 : m_xContext );
717 : }
718 0 : catch ( uno::RuntimeException const & )
719 : {
720 0 : throw;
721 : }
722 0 : catch ( uno::Exception const & )
723 : {
724 : }
725 0 : return m_xPwContainerInteractionHandler;
726 0 : }
727 : }
728 : //------------------------------------------------------------------------------
729 :
730 : uno::Sequence< OUString >
731 0 : UpdateInformationProvider::getServiceNames()
732 : {
733 0 : uno::Sequence< OUString > aServiceList(1);
734 0 : aServiceList[0] = "com.sun.star.deployment.UpdateInformationProvider";
735 0 : return aServiceList;
736 : };
737 :
738 : //------------------------------------------------------------------------------
739 :
740 : OUString
741 0 : UpdateInformationProvider::getImplName()
742 : {
743 0 : return OUString("vnd.sun.UpdateInformationProvider");
744 : }
745 :
746 : //------------------------------------------------------------------------------
747 :
748 : OUString SAL_CALL
749 0 : UpdateInformationProvider::getImplementationName() throw (uno::RuntimeException)
750 : {
751 0 : return getImplName();
752 : }
753 :
754 : //------------------------------------------------------------------------------
755 :
756 : uno::Sequence< OUString > SAL_CALL
757 0 : UpdateInformationProvider::getSupportedServiceNames() throw (uno::RuntimeException)
758 : {
759 0 : return getServiceNames();
760 : }
761 :
762 : //------------------------------------------------------------------------------
763 :
764 : sal_Bool SAL_CALL
765 0 : UpdateInformationProvider::supportsService( OUString const & serviceName ) throw (uno::RuntimeException)
766 : {
767 0 : uno::Sequence< OUString > aServiceNameList = getServiceNames();
768 :
769 0 : for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
770 0 : if( aServiceNameList[n].equals(serviceName) )
771 0 : return sal_True;
772 :
773 0 : return sal_False;
774 : }
775 :
776 : } // anonymous namespace
777 :
778 : //------------------------------------------------------------------------------
779 :
780 : static uno::Reference<uno::XInterface> SAL_CALL
781 0 : createInstance(uno::Reference<uno::XComponentContext> const & xContext)
782 : {
783 0 : return UpdateInformationProvider::createInstance(xContext);
784 : }
785 :
786 : //------------------------------------------------------------------------------
787 :
788 : static const cppu::ImplementationEntry kImplementations_entries[] =
789 : {
790 : {
791 : createInstance,
792 : UpdateInformationProvider::getImplName,
793 : UpdateInformationProvider::getServiceNames,
794 : cppu::createSingleComponentFactory,
795 : NULL,
796 : 0
797 : },
798 : { NULL, NULL, NULL, NULL, NULL, 0 }
799 : } ;
800 :
801 : //------------------------------------------------------------------------------
802 :
803 0 : extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL updatefeed_component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
804 : {
805 : return cppu::component_getFactoryHelper(
806 : pszImplementationName,
807 : pServiceManager,
808 : pRegistryKey,
809 0 : kImplementations_entries) ;
810 : }
811 :
812 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|