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