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