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 { 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 }; 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 }; 101 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) 102 { m_xStream->skipBytes(nBytesToSkip); }; 103 virtual sal_Int32 SAL_CALL available() 104 { return m_xStream->available(); }; 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: 121 ActiveDataSink() {}; 122 123 inline operator uno::Reference< io::XActiveDataSink > () { return this; }; 124 125 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream() { return m_xStream; }; 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 167 virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler() { return uno::Reference< ucb::XProgressHandler >(); }; 168 169 // XWebDAVCommandEnvironment 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: 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 228 virtual ~UpdateInformationEnumeration() {}; 229 230 // XEnumeration 231 sal_Bool SAL_CALL hasMoreElements() { return m_nCount < m_nNodes; }; 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: 286 SingleUpdateInformationEnumeration(const uno::Reference< xml::dom::XElement >& xElement) 287 : m_nCount(0) { m_aEntry.UpdateDocument = xElement; }; 288 virtual ~SingleUpdateInformationEnumeration() {}; 289 290 // XEnumeration 291 sal_Bool SAL_CALL hasMoreElements() { return 0 == m_nCount; }; 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 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 > 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 432 UpdateInformationProvider::~UpdateInformationProvider() 433 { 434 } 435 436 //------------------------------------------------------------------------------ 437 438 rtl::OUString 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 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 > 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 > 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 > 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 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 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 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 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 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 > 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 765 UpdateInformationProvider::getImplName() 766 { 767 return UNISTRING( "vnd.sun.UpdateInformationProvider"); 768 } 769 770 //------------------------------------------------------------------------------ 771 772 rtl::OUString SAL_CALL 773 UpdateInformationProvider::getImplementationName() 774 { 775 return getImplName(); 776 } 777 778 //------------------------------------------------------------------------------ 779 780 uno::Sequence< rtl::OUString > SAL_CALL 781 UpdateInformationProvider::getSupportedServiceNames() 782 { 783 return getServiceNames(); 784 } 785 786 //------------------------------------------------------------------------------ 787 788 sal_Bool SAL_CALL 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 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 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 * 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