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