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