LibreOffice Module desktop (master) 1
unopkg_cmdenv.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
24#include <strings.hrc>
25#include <dp_misc.h>
26#include <dp_shared.hxx>
27#include "unopkg_shared.h"
29#include <rtl/ustrbuf.hxx>
34#include <com/sun/star/lang/WrappedTargetException.hpp>
35#include <com/sun/star/task/XInteractionAbort.hpp>
36#include <com/sun/star/task/XInteractionApprove.hpp>
37#include <com/sun/star/deployment/DeploymentException.hpp>
38#include <com/sun/star/deployment/InstallException.hpp>
39#include <com/sun/star/deployment/LicenseException.hpp>
40#include <com/sun/star/deployment/VersionException.hpp>
41#include <com/sun/star/deployment/PlatformException.hpp>
42#include <com/sun/star/i18n/Collator.hpp>
43#include <com/sun/star/i18n/CollatorOptions.hpp>
44
45#include <dp_version.hxx>
46
47using namespace ::com::sun::star;
48using namespace ::com::sun::star::ucb;
49using namespace ::com::sun::star::uno;
50using namespace ::unopkg;
51
52
53namespace {
54
55
56class CommandEnvironmentImpl
57 : public ::cppu::WeakImplHelper< XCommandEnvironment,
58 task::XInteractionHandler,
59 XProgressHandler >
60{
61 sal_Int32 m_logLevel;
62 bool m_option_force_overwrite;
63 bool m_option_verbose;
64 bool m_option_suppress_license;
65 Reference< XComponentContext > m_xComponentContext;
66 Reference< XProgressHandler > m_xLogFile;
67
69 void update_( Any const & Status );
70 void printLicense(std::u16string_view sName,std::u16string_view sLicense,
71 bool & accept, bool & decline);
72
73public:
74 virtual ~CommandEnvironmentImpl() override;
75 CommandEnvironmentImpl(
76 Reference<XComponentContext> const & xComponentContext,
77 bool option_force_overwrite,
78 bool option_verbose,
79 bool option_suppress_license);
80
81 // XCommandEnvironment
83 getInteractionHandler() override;
84 virtual Reference< XProgressHandler > SAL_CALL getProgressHandler() override;
85
86 // XInteractionHandler
87 virtual void SAL_CALL handle(
88 Reference< task::XInteractionRequest > const & xRequest ) override;
89
90 // XProgressHandler
91 virtual void SAL_CALL push( Any const & Status ) override;
92 virtual void SAL_CALL update( Any const & Status ) override;
93 virtual void SAL_CALL pop() override;
94};
95
96
97CommandEnvironmentImpl::CommandEnvironmentImpl(
98 Reference<XComponentContext> const & xComponentContext,
99 bool option_force_overwrite,
100 bool option_verbose,
101 bool option_suppressLicense)
102 : m_logLevel(0),
103 m_option_force_overwrite( option_force_overwrite ),
104 m_option_verbose( option_verbose ),
105 m_option_suppress_license( option_suppressLicense ),
106 m_xComponentContext(xComponentContext)
107{
108 m_xLogFile.set(
109 xComponentContext->getServiceManager()
110 ->createInstanceWithArgumentsAndContext(
111 "com.sun.star.comp.deployment.ProgressLog",
112 Sequence<Any>(), xComponentContext ),
113 UNO_QUERY_THROW );
114}
115
116
117CommandEnvironmentImpl::~CommandEnvironmentImpl()
118{
119 try {
120 Reference< lang::XComponent > xComp( m_xLogFile, UNO_QUERY );
121 if (xComp.is())
122 xComp->dispose();
123 }
124 catch (const RuntimeException &) {
125 TOOLS_WARN_EXCEPTION( "desktop", "" );
126 }
127}
128
129//May throw exceptions
130void CommandEnvironmentImpl::printLicense(
131 std::u16string_view sName, std::u16string_view sLicense, bool & accept, bool &decline)
132{
133 OUString s1tmp(DpResId(RID_STR_UNOPKG_ACCEPT_LIC_1));
134 OUString s1(s1tmp.replaceAll("$NAME", sName));
135 OUString s2 = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_2);
136 OUString s3 = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_3);
137 OUString s4 = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_4);
138 OUString sYES = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_YES);
139 OUString sY = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_Y);
140 OUString sNO = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_NO);
141 OUString sN = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_N);
142
143 OUString sNewLine("\n");
144
145 dp_misc::writeConsole(Concat2View(sNewLine + sNewLine + s1 + sNewLine + sNewLine));
146 dp_misc::writeConsole(Concat2View(sLicense + sNewLine + sNewLine));
147 dp_misc::writeConsole(Concat2View(s2 + sNewLine));
149
150 //the user may enter "yes" or "no", we compare in a case insensitive way
151 Reference< css::i18n::XCollator > xCollator =
153 xCollator->loadDefaultCollator(
155 css::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE);
156
157 do
158 {
159 OUString sAnswer = dp_misc::readConsole();
160 if (xCollator->compareString(sAnswer, sYES) == 0
161 || xCollator->compareString(sAnswer, sY) == 0)
162 {
163 accept = true;
164 break;
165 }
166 else if(xCollator->compareString(sAnswer, sNO) == 0
167 || xCollator->compareString(sAnswer, sN) == 0)
168 {
169 decline = true;
170 break;
171 }
172 else
173 {
174 dp_misc::writeConsole(Concat2View(sNewLine + sNewLine + s4 + sNewLine));
175 }
176 }
177 while(true);
178}
179
180// XCommandEnvironment
181
183CommandEnvironmentImpl::getInteractionHandler()
184{
185 return this;
186}
187
188
189Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler()
190{
191 return this;
192}
193
194// XInteractionHandler
195
196void CommandEnvironmentImpl::handle(
197 Reference<task::XInteractionRequest> const & xRequest )
198{
199 Any request( xRequest->getRequest() );
200 OSL_ASSERT( request.getValueTypeClass() == TypeClass_EXCEPTION );
201 dp_misc::TRACE("[unopkg_cmdenv.cxx] incoming request:\n"
202 + ::comphelper::anyToString(request) + "\n\n");
203
204 // selections:
205 bool approve = false;
206 bool abort = false;
207
208 lang::WrappedTargetException wtExc;
209 deployment::LicenseException licExc;
210 deployment::InstallException instExc;
211 deployment::PlatformException platExc;
212
213 if (request >>= wtExc) {
214 // ignore intermediate errors of legacy packages, i.e.
215 // former pkgchk behaviour:
216 const Reference<deployment::XPackage> xPackage(
217 wtExc.Context, UNO_QUERY );
218 OSL_ASSERT( xPackage.is() );
219 if (xPackage.is()) {
220 const Reference<deployment::XPackageTypeInfo> xPackageType(
221 xPackage->getPackageType() );
222 OSL_ASSERT( xPackageType.is() );
223 if (xPackageType.is()) {
224 approve = (xPackage->isBundle() &&
225 xPackageType->getMediaType().match(
226 "application/vnd.sun.star.legacy-package-bundle") );
227 }
228 }
229 abort = !approve;
230 if (abort) {
231 // notify cause as error:
232 request = wtExc.TargetException;
233 }
234 else {
235 // handable deployment error signalled, e.g.
236 // bundle item registration failed, notify as warning:
237 update_( wtExc.TargetException );
238 }
239 }
240 else if (request >>= licExc)
241 {
242 if ( !m_option_suppress_license )
243 printLicense(licExc.ExtensionName, licExc.Text, approve, abort);
244 else
245 {
246 approve = true;
247 abort = false;
248 }
249 }
250 else if (request >>= instExc)
251 {
252 //Only if the unopgk was started with gui + extension then the user is asked.
253 //In console mode there is no asking.
254 approve = true;
255 }
256 else if (request >>= platExc)
257 {
258 OUString sMsg(DpResId(RID_STR_UNSUPPORTED_PLATFORM));
259 sMsg = sMsg.replaceAll("%Name", platExc.package->getDisplayName());
260 dp_misc::writeConsole(Concat2View("\n" + sMsg + "\n\n"));
261 approve = true;
262 }
263 else {
264 deployment::VersionException nc_exc;
265 if (request >>= nc_exc) {
266 approve = m_option_force_overwrite ||
267 (::dp_misc::compareVersions(nc_exc.NewVersion, nc_exc.Deployed->getVersion())
269 abort = !approve;
270 }
271 else
272 return; // unknown request => no selection at all
273 }
274
275 if (abort && m_option_verbose)
276 {
277 OUString msg = ::comphelper::anyToString(request);
278 dp_misc::writeConsoleError(Concat2View("\nERROR: " + msg + "\n"));
279 }
280
281 // select:
282 const css::uno::Sequence<css::uno::Reference<css::task::XInteractionContinuation>> xIC = xRequest->getContinuations();
283 for ( auto const& rCont : xIC )
284 {
285 if (approve) {
286 Reference<task::XInteractionApprove> xInteractionApprove(
287 rCont, UNO_QUERY );
288 if (xInteractionApprove.is()) {
289 xInteractionApprove->select();
290 break;
291 }
292 }
293 else if (abort) {
294 Reference<task::XInteractionAbort> xInteractionAbort(
295 rCont, UNO_QUERY );
296 if (xInteractionAbort.is()) {
297 xInteractionAbort->select();
298 break;
299 }
300 }
301 }
302}
303
304// XProgressHandler
305
306void CommandEnvironmentImpl::push( Any const & Status )
307{
308 update_( Status );
309 OSL_ASSERT( m_logLevel >= 0 );
310 ++m_logLevel;
311 if (m_xLogFile.is())
312 m_xLogFile->push( Status );
313}
314
315
316void CommandEnvironmentImpl::update_( Any const & Status )
317{
318 if (! Status.hasValue())
319 return;
320 bool bUseErr = false;
321 OUString msg;
322 if (Status >>= msg) {
323 if (! m_option_verbose)
324 return;
325 }
326 else {
327 OUStringBuffer buf( "WARNING: " );
328 deployment::DeploymentException dp_exc;
329 if (Status >>= dp_exc) {
330 buf.append( dp_exc.Message + ", Cause: " + ::comphelper::anyToString(dp_exc.Cause) );
331 }
332 else {
333 buf.append( ::comphelper::anyToString(Status) );
334 }
335 msg = buf.makeStringAndClear();
336 bUseErr = true;
337 }
338 OSL_ASSERT( m_logLevel >= 0 );
339 for ( sal_Int32 n = 0; n < m_logLevel; ++n )
340 {
341 if (bUseErr)
343 else
345 }
346
347 if (bUseErr)
348 dp_misc::writeConsoleError(Concat2View(msg + "\n"));
349 else
350 dp_misc::writeConsole(Concat2View(msg + "\n"));
351}
352
353
354void CommandEnvironmentImpl::update( Any const & Status )
355{
356 update_( Status );
357 if (m_xLogFile.is())
358 m_xLogFile->update( Status );
359}
360
361
362void CommandEnvironmentImpl::pop()
363{
364 OSL_ASSERT( m_logLevel > 0 );
365 --m_logLevel;
366 if (m_xLogFile.is())
367 m_xLogFile->pop();
368}
369
370
371} // anon namespace
372
373namespace unopkg {
374
375
376Reference< XCommandEnvironment > createCmdEnv(
377 Reference< XComponentContext > const & xContext,
378 bool option_force_overwrite,
379 bool option_verbose,
380 bool option_suppress_license)
381{
382 return new CommandEnvironmentImpl(
383 xContext, option_force_overwrite, option_verbose, option_suppress_license);
384}
385} // unopkg
386
387/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OUString getUILocale()
#define TOOLS_WARN_EXCEPTION(area, stream)
Reference< XComponentContext > const m_xComponentContext
OUString DpResId(TranslateId aId)
Definition: dp_misc.cxx:555
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2642
sal_Int64 n
const LanguageTag & getLocale()
OUString readConsole()
reads from the console.
Definition: dp_misc.cxx:473
void writeConsoleError(std::u16string_view sText)
writes the argument to the console using the error stream.
Definition: dp_misc.cxx:468
void TRACE(OUString const &sText)
print the text to the console in a debug build.
Definition: dp_misc.cxx:486
void writeConsole(std::u16string_view sText)
writes the argument string to the console.
Definition: dp_misc.cxx:463
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(std::u16string_view version1, std::u16string_view version2)
Definition: dp_version.cxx:42
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Reference< XCommandEnvironment > createCmdEnv(Reference< XComponentContext > const &xContext, bool option_force_overwrite, bool option_verbose, bool option_suppress_license)
bool update()
Definition: updater.cxx:286