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