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