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