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