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_desktop.hxx" 30 31 #include "dp_gui_updatedata.hxx" 32 33 #include "sal/config.h" 34 #include "osl/file.hxx" 35 #include "osl/conditn.hxx" 36 #include "cppuhelper/exc_hlp.hxx" 37 #include "tools/resid.hxx" 38 #include "tools/resmgr.hxx" 39 #include "tools/solar.h" 40 #include "tools/string.hxx" 41 #include "vcl/dialog.hxx" 42 #include "vcl/msgbox.hxx" 43 #include "vcl/svapp.hxx" 44 #include "vos/mutex.hxx" 45 #include "vcl/dialog.hxx" 46 #include "cppuhelper/implbase3.hxx" 47 48 #include "com/sun/star/beans/PropertyValue.hpp" 49 #include "com/sun/star/beans/NamedValue.hpp" 50 #include "com/sun/star/xml/dom/XElement.hpp" 51 #include "com/sun/star/xml/dom/XNode.hpp" 52 #include "com/sun/star/xml/dom/XNodeList.hpp" 53 #include "com/sun/star/ucb/NameClash.hpp" 54 #include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" 55 #include "com/sun/star/ucb/XCommandEnvironment.hpp" 56 #include "com/sun/star/ucb/XProgressHandler.hpp" 57 #include "com/sun/star/deployment/XExtensionManager.hpp" 58 #include "com/sun/star/deployment/ExtensionManager.hpp" 59 #include "com/sun/star/deployment/XUpdateInformationProvider.hpp" 60 #include "com/sun/star/deployment/DependencyException.hpp" 61 #include "com/sun/star/deployment/LicenseException.hpp" 62 #include "com/sun/star/deployment/VersionException.hpp" 63 #include "com/sun/star/deployment/ui/LicenseDialog.hpp" 64 #include "com/sun/star/task/XInteractionHandler.hpp" 65 #include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" 66 #include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" 67 #include "com/sun/star/task/XInteractionAbort.hpp" 68 #include "com/sun/star/task/XInteractionApprove.hpp" 69 70 #include "dp_descriptioninfoset.hxx" 71 #include "dp_gui.hrc" 72 #include "dp_gui_updateinstalldialog.hxx" 73 #include "dp_gui_shared.hxx" 74 #include "dp_gui_updatedata.hxx" 75 #include "dp_ucb.h" 76 #include "dp_misc.h" 77 #include "dp_version.hxx" 78 #include "dp_gui_thread.hxx" 79 #include "dp_gui_extensioncmdqueue.hxx" 80 #include "ucbhelper/content.hxx" 81 #include "osl/mutex.hxx" 82 #include "vos/mutex.hxx" 83 #include "rtl/ref.hxx" 84 #include "com/sun/star/uno/Sequence.h" 85 #include "comphelper/anytostring.hxx" 86 #include "toolkit/helper/vclunohelper.hxx" 87 88 #include <vector> 89 90 class Window; 91 92 namespace cssu = ::com::sun::star::uno; 93 namespace css = ::com::sun::star; 94 95 using ::rtl::OUString; 96 97 98 namespace dp_gui { 99 100 class UpdateInstallDialog::Thread: public dp_gui::Thread { 101 friend class UpdateCommandEnv; 102 public: 103 Thread(cssu::Reference< cssu::XComponentContext > ctx, 104 UpdateInstallDialog & dialog, std::vector< dp_gui::UpdateData > & aVecUpdateData); 105 106 void stop(); 107 108 109 110 private: 111 Thread(Thread &); // not defined 112 void operator =(Thread &); // not defined 113 114 virtual ~Thread(); 115 116 virtual void execute(); 117 void downloadExtensions(); 118 void download(::rtl::OUString const & aUrls, UpdateData & aUpdatData); 119 void installExtensions(); 120 void removeTempDownloads(); 121 122 UpdateInstallDialog & m_dialog; 123 cssu::Reference< css::deployment::XUpdateInformationProvider > 124 m_updateInformation; 125 126 // guarded by Application::GetSolarMutex(): 127 cssu::Reference< css::task::XAbortChannel > m_abort; 128 cssu::Reference< cssu::XComponentContext > m_xComponentContext; 129 std::vector< dp_gui::UpdateData > & m_aVecUpdateData; 130 ::rtl::Reference<UpdateCommandEnv> m_updateCmdEnv; 131 132 //A folder which is created in the temp directory in which then the updates are downloaded 133 ::rtl::OUString m_sDownloadFolder; 134 135 bool m_stop; 136 137 }; 138 139 class UpdateCommandEnv 140 : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, 141 css::task::XInteractionHandler, 142 css::ucb::XProgressHandler > 143 { 144 friend class UpdateInstallDialog::Thread; 145 146 UpdateInstallDialog & m_updateDialog; 147 ::rtl::Reference<UpdateInstallDialog::Thread> m_installThread; 148 cssu::Reference< cssu::XComponentContext > m_xContext; 149 150 public: 151 virtual ~UpdateCommandEnv(); 152 UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, 153 UpdateInstallDialog & updateDialog, 154 ::rtl::Reference<UpdateInstallDialog::Thread>const & thread); 155 156 // XCommandEnvironment 157 virtual cssu::Reference<css::task::XInteractionHandler > SAL_CALL 158 getInteractionHandler() throw (cssu::RuntimeException); 159 virtual cssu::Reference<css::ucb::XProgressHandler > 160 SAL_CALL getProgressHandler() throw (cssu::RuntimeException); 161 162 // XInteractionHandler 163 virtual void SAL_CALL handle( 164 cssu::Reference<css::task::XInteractionRequest > const & xRequest ) 165 throw (cssu::RuntimeException); 166 167 // XProgressHandler 168 virtual void SAL_CALL push( cssu::Any const & Status ) 169 throw (cssu::RuntimeException); 170 virtual void SAL_CALL update( cssu::Any const & Status ) 171 throw (cssu::RuntimeException); 172 virtual void SAL_CALL pop() throw (cssu::RuntimeException); 173 }; 174 175 176 UpdateInstallDialog::Thread::Thread( 177 cssu::Reference< cssu::XComponentContext> xCtx, 178 UpdateInstallDialog & dialog, 179 std::vector< dp_gui::UpdateData > & aVecUpdateData): 180 m_dialog(dialog), 181 m_xComponentContext(xCtx), 182 m_aVecUpdateData(aVecUpdateData), 183 m_updateCmdEnv(new UpdateCommandEnv(xCtx, m_dialog, this)), 184 m_stop(false) 185 {} 186 187 void UpdateInstallDialog::Thread::stop() { 188 cssu::Reference< css::task::XAbortChannel > abort; 189 { 190 vos::OGuard g(Application::GetSolarMutex()); 191 abort = m_abort; 192 m_stop = true; 193 } 194 if (abort.is()) { 195 abort->sendAbort(); 196 } 197 } 198 199 UpdateInstallDialog::Thread::~Thread() {} 200 201 void UpdateInstallDialog::Thread::execute() 202 { 203 try { 204 downloadExtensions(); 205 installExtensions(); 206 } 207 catch (...) 208 { 209 } 210 211 //clean up the temp directories 212 try { 213 removeTempDownloads(); 214 } catch( ... ) { 215 } 216 217 { 218 //make sure m_dialog is still alive 219 ::vos::OGuard g(Application::GetSolarMutex()); 220 if (! m_stop) 221 m_dialog.updateDone(); 222 } 223 //UpdateCommandEnv keeps a reference to Thread and prevents destruction. Therefore remove it. 224 m_updateCmdEnv->m_installThread.clear(); 225 } 226 227 228 UpdateInstallDialog::UpdateInstallDialog( 229 Window * parent, 230 std::vector<dp_gui::UpdateData> & aVecUpdateData, 231 cssu::Reference< cssu::XComponentContext > const & xCtx): 232 ModalDialog( 233 parent, 234 DpGuiResId(RID_DLG_UPDATEINSTALL)), 235 236 m_thread(new Thread(xCtx, *this, aVecUpdateData)), 237 m_xComponentContext(xCtx), 238 m_bError(false), 239 m_bNoEntry(true), 240 m_bActivated(false), 241 m_sInstalling(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_INSTALLING))), 242 m_sFinished(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_FINISHED))), 243 m_sNoErrors(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_NO_ERRORS))), 244 m_sErrorDownload(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD))), 245 m_sErrorInstallation(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION))), 246 m_sErrorLicenseDeclined(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED))), 247 m_sNoInstall(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL))), 248 m_sThisErrorOccurred(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED))), 249 m_ft_action(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_DOWNLOADING)), 250 m_statusbar(this,DpGuiResId(RID_DLG_UPDATE_INSTALL_STATUSBAR)), 251 m_ft_extension_name(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NAME)), 252 m_ft_results(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_RESULTS)), 253 m_mle_info(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_INFO)), 254 m_line(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_LINE)), 255 m_help(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_HELP)), 256 m_ok(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_OK)), 257 m_cancel(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_ABORT)) 258 { 259 FreeResource(); 260 261 m_xExtensionManager = css::deployment::ExtensionManager::get( xCtx ); 262 263 m_cancel.SetClickHdl(LINK(this, UpdateInstallDialog, cancelHandler)); 264 m_mle_info.EnableCursor(sal_False); 265 if ( ! dp_misc::office_is_running()) 266 m_help.Disable(); 267 } 268 269 UpdateInstallDialog::~UpdateInstallDialog() {} 270 271 sal_Bool UpdateInstallDialog::Close() 272 { 273 m_thread->stop(); 274 return ModalDialog::Close(); 275 } 276 277 short UpdateInstallDialog::Execute() 278 { 279 m_thread->launch(); 280 return ModalDialog::Execute(); 281 } 282 283 284 // make sure the solar mutex is locked before calling 285 void UpdateInstallDialog::updateDone() 286 { 287 if (!m_bError) 288 m_mle_info.InsertText(m_sNoErrors); 289 m_ok.Enable(); 290 m_ok.GrabFocus(); 291 m_cancel.Disable(); 292 } 293 // make sure the solar mutex is locked before calling 294 //sets an error message in the text area 295 void UpdateInstallDialog::setError(INSTALL_ERROR err, ::rtl::OUString const & sExtension, 296 OUString const & exceptionMessage) 297 { 298 String sError; 299 m_bError = true; 300 301 switch (err) 302 { 303 case ERROR_DOWNLOAD: 304 sError = m_sErrorDownload; 305 break; 306 case ERROR_INSTALLATION: 307 sError = m_sErrorInstallation; 308 break; 309 case ERROR_LICENSE_DECLINED: 310 sError = m_sErrorLicenseDeclined; 311 break; 312 313 default: 314 OSL_ASSERT(0); 315 } 316 317 sError.SearchAndReplace(String(OUSTR("%NAME")), String(sExtension), 0); 318 //We want to have an empty line between the error messages. However, 319 //there shall be no empty line after the last entry. 320 if (m_bNoEntry) 321 m_bNoEntry = false; 322 else 323 m_mle_info.InsertText(OUSTR("\n")); 324 m_mle_info.InsertText(sError); 325 //Insert more information about the error 326 if (exceptionMessage.getLength()) 327 m_mle_info.InsertText(m_sThisErrorOccurred + exceptionMessage + OUSTR("\n")); 328 329 m_mle_info.InsertText(m_sNoInstall); 330 m_mle_info.InsertText(OUSTR("\n")); 331 } 332 333 void UpdateInstallDialog::setError(OUString const & exceptionMessage) 334 { 335 m_bError = true; 336 m_mle_info.InsertText(exceptionMessage + OUSTR("\n")); 337 } 338 339 IMPL_LINK(UpdateInstallDialog, cancelHandler, void *, EMPTYARG) 340 { 341 m_thread->stop(); 342 EndDialog(RET_CANCEL); 343 return 0; 344 } 345 346 //------------------------------------------------------------------------------------------------ 347 348 void UpdateInstallDialog::Thread::downloadExtensions() 349 { 350 try 351 { 352 //create the download directory in the temp folder 353 OUString sTempDir; 354 if (::osl::FileBase::getTempDirURL(sTempDir) != ::osl::FileBase::E_None) 355 throw cssu::Exception(OUSTR("Could not get URL for the temp directory. No extensions will be installed."), 0); 356 357 //create a unique name for the directory 358 OUString tempEntry, destFolder; 359 if (::osl::File::createTempFile(&sTempDir, 0, &tempEntry ) != ::osl::File::E_None) 360 throw cssu::Exception(OUSTR("Could not create a temporary file in ") + sTempDir + 361 OUSTR(". No extensions will be installed"), 0 ); 362 363 tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); 364 365 destFolder = dp_misc::makeURL( sTempDir, tempEntry ); 366 destFolder += OUSTR("_"); 367 m_sDownloadFolder = destFolder; 368 try 369 { 370 dp_misc::create_folder(0, destFolder, m_updateCmdEnv.get(), true ); 371 } catch (cssu::Exception & e) 372 { 373 throw cssu::Exception(e.Message + OUSTR(" No extensions will be installed."), 0); 374 } 375 376 377 sal_uInt16 count = 0; 378 typedef std::vector<UpdateData>::iterator It; 379 for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); i++) 380 { 381 UpdateData & curData = *i; 382 383 if (!curData.aUpdateInfo.is() || curData.aUpdateSource.is()) 384 continue; 385 //We assume that m_aVecUpdateData contains only information about extensions which 386 //can be downloaded directly. 387 OSL_ASSERT(curData.sWebsiteURL.getLength() == 0); 388 389 //update the name of the extension which is to be downloaded 390 { 391 ::vos::OGuard g(Application::GetSolarMutex()); 392 if (m_stop) { 393 return; 394 } 395 m_dialog.m_ft_extension_name.SetText(curData.aInstalledPackage->getDisplayName()); 396 sal_uInt16 prog = (sal::static_int_cast<sal_uInt16>(100) * ++count) / 397 sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size()); 398 m_dialog.m_statusbar.SetValue(prog); 399 } 400 dp_misc::DescriptionInfoset info(m_xComponentContext, curData.aUpdateInfo); 401 //remember occurring exceptions in case we need to print out error information 402 ::std::vector< ::std::pair<OUString, cssu::Exception> > vecExceptions; 403 cssu::Sequence<OUString> seqDownloadURLs = info.getUpdateDownloadUrls(); 404 OSL_ENSURE(seqDownloadURLs.getLength() > 0, "No download URL provided!"); 405 for (sal_Int32 j = 0; j < seqDownloadURLs.getLength(); j++) 406 { 407 try 408 { 409 OSL_ENSURE(seqDownloadURLs[j].getLength() > 0, "Download URL is empty!"); 410 download(seqDownloadURLs[j], curData); 411 if (curData.sLocalURL.getLength() > 0) 412 break; 413 } 414 catch ( cssu::Exception & e ) 415 { 416 vecExceptions.push_back( ::std::make_pair(seqDownloadURLs[j], e)); 417 //There can be several different errors, for example, the URL is wrong, webserver cannot be reached, 418 //name cannot be resolved. The UCB helper API does not specify different special exceptions for these 419 //cases. Therefore ignore and continue. 420 continue; 421 } 422 } 423 //update the progress and display download error 424 { 425 ::vos::OGuard g(Application::GetSolarMutex()); 426 if (m_stop) { 427 return; 428 } 429 if (curData.sLocalURL.getLength() == 0) 430 { 431 //Construct a string of all messages contained in the exceptions plus the respective download URLs 432 ::rtl::OUStringBuffer buf(256); 433 typedef ::std::vector< ::std::pair<OUString, cssu::Exception > >::const_iterator CIT; 434 for (CIT j = vecExceptions.begin(); j != vecExceptions.end(); j++) 435 { 436 if (j != vecExceptions.begin()) 437 buf.appendAscii("\n"); 438 buf.append(OUSTR("Could not download ")); 439 buf.append(j->first); 440 buf.appendAscii(". "); 441 buf.append(j->second.Message); 442 } 443 m_dialog.setError(UpdateInstallDialog::ERROR_DOWNLOAD, curData.aInstalledPackage->getDisplayName(), 444 buf.makeStringAndClear()); 445 } 446 } 447 448 } 449 } 450 catch (cssu::Exception & e) 451 { 452 ::vos::OGuard g(Application::GetSolarMutex()); 453 if (m_stop) { 454 return; 455 } 456 m_dialog.setError(e.Message); 457 } 458 } 459 void UpdateInstallDialog::Thread::installExtensions() 460 { 461 //Update the fix text in the dialog to "Installing extensions..." 462 { 463 vos::OGuard g(Application::GetSolarMutex()); 464 if (m_stop) { 465 return; 466 } 467 m_dialog.m_ft_action.SetText(m_dialog.m_sInstalling); 468 m_dialog.m_statusbar.SetValue(0); 469 } 470 471 sal_uInt16 count = 0; 472 typedef std::vector<UpdateData>::iterator It; 473 for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); i++, count++) 474 { 475 //update the name of the extension which is to be installed 476 { 477 ::vos::OGuard g(Application::GetSolarMutex()); 478 if (m_stop) { 479 return; 480 } 481 //we only show progress after an extension has been installed. 482 if (count > 0) { 483 m_dialog.m_statusbar.SetValue( 484 (sal::static_int_cast<sal_uInt16>(100) * count) / 485 sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size())); 486 } 487 m_dialog.m_ft_extension_name.SetText(i->aInstalledPackage->getDisplayName()); 488 } 489 // TimeValue v = {1, 0}; 490 // osl::Thread::wait(v); 491 bool bError = false; 492 bool bLicenseDeclined = false; 493 cssu::Reference<css::deployment::XPackage> xExtension; 494 UpdateData & curData = *i; 495 cssu::Exception exc; 496 try 497 { 498 cssu::Reference< css::task::XAbortChannel > xAbortChannel( 499 curData.aInstalledPackage->createAbortChannel() ); 500 { 501 vos::OGuard g(Application::GetSolarMutex()); 502 if (m_stop) { 503 return; 504 } 505 m_abort = xAbortChannel; 506 } 507 if (!curData.aUpdateSource.is() && curData.sLocalURL.getLength()) 508 { 509 css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); 510 if (!curData.bIsShared) 511 xExtension = m_dialog.getExtensionManager()->addExtension( 512 curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), 513 OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); 514 else 515 xExtension = m_dialog.getExtensionManager()->addExtension( 516 curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), 517 OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); 518 } 519 else if (curData.aUpdateSource.is()) 520 { 521 OSL_ASSERT(curData.aUpdateSource.is()); 522 //I am not sure if we should obtain the install properties and pass them into 523 //add extension. Currently it contains only "SUPPRESS_LICENSE". So it it could happen 524 //that a license is displayed when updating from the shared repository, although the 525 //shared extension was installed using "SUPPRESS_LICENSE". 526 css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); 527 if (!curData.bIsShared) 528 xExtension = m_dialog.getExtensionManager()->addExtension( 529 curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), 530 OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); 531 else 532 xExtension = m_dialog.getExtensionManager()->addExtension( 533 curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), 534 OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); 535 } 536 } 537 catch (css::deployment::DeploymentException & de) 538 { 539 if (de.Cause.has<css::deployment::LicenseException>()) 540 { 541 bLicenseDeclined = true; 542 } 543 else 544 { 545 exc = de.Cause.get<cssu::Exception>(); 546 bError = true; 547 } 548 } 549 catch (cssu::Exception& e) 550 { 551 exc = e; 552 bError = true; 553 } 554 555 if (bLicenseDeclined) 556 { 557 ::vos::OGuard g(Application::GetSolarMutex()); 558 if (m_stop) { 559 return; 560 } 561 m_dialog.setError(UpdateInstallDialog::ERROR_LICENSE_DECLINED, 562 curData.aInstalledPackage->getDisplayName(), OUString()); 563 } 564 else if (!xExtension.is() || bError) 565 { 566 ::vos::OGuard g(Application::GetSolarMutex()); 567 if (m_stop) { 568 return; 569 } 570 m_dialog.setError(UpdateInstallDialog::ERROR_INSTALLATION, 571 curData.aInstalledPackage->getDisplayName(), exc.Message); 572 } 573 } 574 { 575 vos::OGuard g(Application::GetSolarMutex()); 576 if (m_stop) { 577 return; 578 } 579 m_dialog.m_statusbar.SetValue(100); 580 m_dialog.m_ft_extension_name.SetText(OUString()); 581 m_dialog.m_ft_action.SetText(m_dialog.m_sFinished); 582 } 583 } 584 585 void UpdateInstallDialog::Thread::removeTempDownloads() 586 { 587 if (m_sDownloadFolder.getLength()) 588 { 589 dp_misc::erase_path(m_sDownloadFolder, 590 cssu::Reference<css::ucb::XCommandEnvironment>(),false /* no throw: ignore errors */ ); 591 //remove also the temp file which we have used to create the unique name 592 OUString tempFile = m_sDownloadFolder.copy(0, m_sDownloadFolder.getLength() - 1); 593 dp_misc::erase_path(tempFile, cssu::Reference<css::ucb::XCommandEnvironment>(),false); 594 m_sDownloadFolder = OUString(); 595 } 596 } 597 598 599 void UpdateInstallDialog::Thread::download(OUString const & sDownloadURL, UpdateData & aUpdateData) 600 { 601 { 602 ::vos::OGuard g(Application::GetSolarMutex()); 603 if (m_stop) { 604 return; 605 } 606 } 607 608 OSL_ASSERT(m_sDownloadFolder.getLength()); 609 OUString destFolder, tempEntry; 610 if (::osl::File::createTempFile( 611 &m_sDownloadFolder, 612 0, &tempEntry ) != ::osl::File::E_None) 613 { 614 //ToDo feedback in window that download of this component failed 615 throw cssu::Exception(OUSTR("Could not create temporary file in folder ") + destFolder + OUSTR("."), 0); 616 } 617 tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); 618 619 destFolder = dp_misc::makeURL( m_sDownloadFolder, tempEntry ); 620 destFolder += OUSTR("_"); 621 622 ::ucbhelper::Content destFolderContent; 623 dp_misc::create_folder( &destFolderContent, destFolder, m_updateCmdEnv.get() ); 624 625 ::ucbhelper::Content sourceContent; 626 dp_misc::create_ucb_content( &sourceContent, sDownloadURL, m_updateCmdEnv.get() ); 627 628 const OUString sTitle(sourceContent.getPropertyValue( 629 dp_misc::StrTitle::get() ).get<OUString>() ); 630 631 if (destFolderContent.transferContent( 632 sourceContent, ::ucbhelper::InsertOperation_COPY, 633 sTitle, css::ucb::NameClash::OVERWRITE )) 634 { 635 //the user may have cancelled the dialog because downloading took to long 636 { 637 ::vos::OGuard g(Application::GetSolarMutex()); 638 if (m_stop) { 639 return; 640 } 641 //all errors should be handeld by the command environment. 642 aUpdateData.sLocalURL = destFolder + OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + sTitle; 643 } 644 } 645 } 646 647 648 // ------------------------------------------------------------------------------------------------------- 649 650 UpdateCommandEnv::UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, 651 UpdateInstallDialog & updateDialog, 652 ::rtl::Reference<UpdateInstallDialog::Thread>const & thread) 653 : m_updateDialog( updateDialog ), 654 m_installThread(thread), 655 m_xContext(xCtx) 656 { 657 } 658 659 UpdateCommandEnv::~UpdateCommandEnv() 660 { 661 } 662 663 664 // XCommandEnvironment 665 //______________________________________________________________________________ 666 cssu::Reference<css::task::XInteractionHandler> UpdateCommandEnv::getInteractionHandler() 667 throw (cssu::RuntimeException) 668 { 669 return this; 670 } 671 672 //______________________________________________________________________________ 673 cssu::Reference<css::ucb::XProgressHandler> UpdateCommandEnv::getProgressHandler() 674 throw (cssu::RuntimeException) 675 { 676 return this; 677 } 678 679 // XInteractionHandler 680 void UpdateCommandEnv::handle( 681 cssu::Reference< css::task::XInteractionRequest> const & xRequest ) 682 throw (cssu::RuntimeException) 683 { 684 cssu::Any request( xRequest->getRequest() ); 685 OSL_ASSERT( request.getValueTypeClass() == cssu::TypeClass_EXCEPTION ); 686 dp_misc::TRACE(OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n") 687 + ::comphelper::anyToString(request) + OUSTR("\n\n")); 688 689 css::deployment::VersionException verExc; 690 bool approve = false; 691 bool abort = false; 692 693 if (request >>= verExc) 694 { //We must catch the version exception during the update, 695 //because otherwise the user would be confronted with the dialogs, asking 696 //them if they want to replace an already installed version of the same extension. 697 //During an update we assume that we always want to replace the old version with the 698 //new version. 699 approve = true; 700 } 701 702 if (approve == false && abort == false) 703 { 704 //forward to interaction handler for main dialog. 705 handleInteractionRequest( m_xContext, xRequest ); 706 } 707 else 708 { 709 // select: 710 cssu::Sequence< cssu::Reference< css::task::XInteractionContinuation > > conts( 711 xRequest->getContinuations() ); 712 cssu::Reference< css::task::XInteractionContinuation > const * pConts = 713 conts.getConstArray(); 714 sal_Int32 len = conts.getLength(); 715 for ( sal_Int32 pos = 0; pos < len; ++pos ) 716 { 717 if (approve) { 718 cssu::Reference< css::task::XInteractionApprove > xInteractionApprove( 719 pConts[ pos ], cssu::UNO_QUERY ); 720 if (xInteractionApprove.is()) { 721 xInteractionApprove->select(); 722 // don't query again for ongoing continuations: 723 approve = false; 724 } 725 } 726 else if (abort) { 727 cssu::Reference< css::task::XInteractionAbort > xInteractionAbort( 728 pConts[ pos ], cssu::UNO_QUERY ); 729 if (xInteractionAbort.is()) { 730 xInteractionAbort->select(); 731 // don't query again for ongoing continuations: 732 abort = false; 733 } 734 } 735 } 736 } 737 } 738 739 // XProgressHandler 740 void UpdateCommandEnv::push( cssu::Any const & /*Status*/ ) 741 throw (cssu::RuntimeException) 742 { 743 } 744 745 746 void UpdateCommandEnv::update( cssu::Any const & /*Status */) 747 throw (cssu::RuntimeException) 748 { 749 } 750 751 void UpdateCommandEnv::pop() throw (cssu::RuntimeException) 752 { 753 } 754 755 756 } //end namespace dp_gui 757