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: 84 InputStreamWrapper(const uno::Reference< io::XInputStream >& rxStream) : 85 m_xStream(rxStream) {}; 86 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 }; 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 }; 103 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) 104 throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) 105 { m_xStream->skipBytes(nBytesToSkip); }; 106 virtual sal_Int32 SAL_CALL available() 107 throw (io::NotConnectedException, io::IOException, uno::RuntimeException) 108 { return m_xStream->available(); }; 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: 126 ActiveDataSink() {}; 127 128 inline operator uno::Reference< io::XActiveDataSink > () { return this; }; 129 130 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream() 131 throw (uno::RuntimeException) { return m_xStream; }; 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 177 virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler() 178 throw ( uno::RuntimeException ) { return uno::Reference< ucb::XProgressHandler >(); }; 179 180 // XWebDAVCommandEnvironment 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: 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 243 virtual ~UpdateInformationEnumeration() {}; 244 245 // XEnumeration 246 sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException) { return m_nCount < m_nNodes; }; 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: 301 SingleUpdateInformationEnumeration(const uno::Reference< xml::dom::XElement >& xElement) 302 : m_nCount(0) { m_aEntry.UpdateDocument = xElement; }; 303 virtual ~SingleUpdateInformationEnumeration() {}; 304 305 // XEnumeration 306 sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException) { return 0 == m_nCount; }; 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 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 > 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 447 UpdateInformationProvider::~UpdateInformationProvider() 448 { 449 } 450 451 //------------------------------------------------------------------------------ 452 453 rtl::OUString 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 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 > 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 > 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 > 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 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 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 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 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 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 > 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 782 UpdateInformationProvider::getImplName() 783 { 784 return UNISTRING( "vnd.sun.UpdateInformationProvider"); 785 } 786 787 //------------------------------------------------------------------------------ 788 789 rtl::OUString SAL_CALL 790 UpdateInformationProvider::getImplementationName() throw (uno::RuntimeException) 791 { 792 return getImplName(); 793 } 794 795 //------------------------------------------------------------------------------ 796 797 uno::Sequence< rtl::OUString > SAL_CALL 798 UpdateInformationProvider::getSupportedServiceNames() throw (uno::RuntimeException) 799 { 800 return getServiceNames(); 801 } 802 803 //------------------------------------------------------------------------------ 804 805 sal_Bool SAL_CALL 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 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 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 * 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