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 
21 #include <strings.hrc>
22 #include <dp_misc.h>
23 #include <dp_shared.hxx>
24 #include "unopkg_shared.h"
26 #include <rtl/ustrbuf.hxx>
27 #include <cppuhelper/implbase.hxx>
29 #include <tools/diagnose_ex.h>
30 #include <unotools/configmgr.hxx>
31 #include <com/sun/star/lang/WrappedTargetException.hpp>
32 #include <com/sun/star/task/XInteractionAbort.hpp>
33 #include <com/sun/star/task/XInteractionApprove.hpp>
34 #include <com/sun/star/deployment/DeploymentException.hpp>
35 #include <com/sun/star/deployment/InstallException.hpp>
36 #include <com/sun/star/deployment/LicenseException.hpp>
37 #include <com/sun/star/deployment/VersionException.hpp>
38 #include <com/sun/star/deployment/PlatformException.hpp>
39 #include <com/sun/star/i18n/Collator.hpp>
40 #include <com/sun/star/i18n/CollatorOptions.hpp>
41 
42 #include <dp_version.hxx>
43 
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::ucb;
46 using namespace ::com::sun::star::uno;
47 using namespace ::unopkg;
48 
49 
50 namespace {
51 
52 
53 class CommandEnvironmentImpl
54  : public ::cppu::WeakImplHelper< XCommandEnvironment,
55  task::XInteractionHandler,
56  XProgressHandler >
57 {
58  sal_Int32 m_logLevel;
59  bool m_option_force_overwrite;
60  bool m_option_verbose;
61  bool m_option_suppress_license;
64 
66  void update_( Any const & Status );
67  void printLicense(const OUString & sName,const OUString& sLicense,
68  bool & accept, bool & decline);
69 
70 public:
71  virtual ~CommandEnvironmentImpl() override;
72  CommandEnvironmentImpl(
73  Reference<XComponentContext> const & xComponentContext,
74  bool option_force_overwrite,
75  bool option_verbose,
76  bool option_suppress_license);
77 
78  // XCommandEnvironment
79  virtual Reference< task::XInteractionHandler > SAL_CALL
80  getInteractionHandler() override;
81  virtual Reference< XProgressHandler > SAL_CALL getProgressHandler() override;
82 
83  // XInteractionHandler
84  virtual void SAL_CALL handle(
85  Reference< task::XInteractionRequest > const & xRequest ) override;
86 
87  // XProgressHandler
88  virtual void SAL_CALL push( Any const & Status ) override;
89  virtual void SAL_CALL update( Any const & Status ) override;
90  virtual void SAL_CALL pop() override;
91 };
92 
93 
94 CommandEnvironmentImpl::CommandEnvironmentImpl(
95  Reference<XComponentContext> const & xComponentContext,
96  bool option_force_overwrite,
97  bool option_verbose,
98  bool option_suppressLicense)
99  : m_logLevel(0),
100  m_option_force_overwrite( option_force_overwrite ),
101  m_option_verbose( option_verbose ),
102  m_option_suppress_license( option_suppressLicense ),
103  m_xComponentContext(xComponentContext)
104 {
105  m_xLogFile.set(
106  xComponentContext->getServiceManager()
107  ->createInstanceWithArgumentsAndContext(
108  "com.sun.star.comp.deployment.ProgressLog",
109  Sequence<Any>(), xComponentContext ),
110  UNO_QUERY_THROW );
111 }
112 
113 
114 CommandEnvironmentImpl::~CommandEnvironmentImpl()
115 {
116  try {
117  Reference< lang::XComponent > xComp( m_xLogFile, UNO_QUERY );
118  if (xComp.is())
119  xComp->dispose();
120  }
121  catch (const RuntimeException &) {
122  TOOLS_WARN_EXCEPTION( "desktop", "" );
123  }
124 }
125 
126 //May throw exceptions
127 void CommandEnvironmentImpl::printLicense(
128  const OUString & sName, const OUString& sLicense, bool & accept, bool &decline)
129 {
130  OUString s1tmp(DpResId(RID_STR_UNOPKG_ACCEPT_LIC_1));
131  OUString s1(s1tmp.replaceAll("$NAME", sName));
132  OUString s2 = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_2);
133  OUString s3 = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_3);
134  OUString s4 = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_4);
135  OUString sYES = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_YES);
136  OUString sY = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_Y);
137  OUString sNO = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_NO);
138  OUString sN = DpResId(RID_STR_UNOPKG_ACCEPT_LIC_N);
139 
140  OUString sNewLine("\n");
141 
142  dp_misc::writeConsole(sNewLine + sNewLine + s1 + sNewLine + sNewLine);
143  dp_misc::writeConsole(sLicense + sNewLine + sNewLine);
144  dp_misc::writeConsole(s2 + sNewLine);
146 
147  //the user may enter "yes" or "no", we compare in a case insensitive way
148  Reference< css::i18n::XCollator > xCollator =
150  xCollator->loadDefaultCollator(
152  css::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE);
153 
154  do
155  {
156  OUString sAnswer = dp_misc::readConsole();
157  if (xCollator->compareString(sAnswer, sYES) == 0
158  || xCollator->compareString(sAnswer, sY) == 0)
159  {
160  accept = true;
161  break;
162  }
163  else if(xCollator->compareString(sAnswer, sNO) == 0
164  || xCollator->compareString(sAnswer, sN) == 0)
165  {
166  decline = true;
167  break;
168  }
169  else
170  {
171  dp_misc::writeConsole(sNewLine + sNewLine + s4 + sNewLine);
172  }
173  }
174  while(true);
175 }
176 
177 // XCommandEnvironment
178 
179 Reference< task::XInteractionHandler >
180 CommandEnvironmentImpl::getInteractionHandler()
181 {
182  return this;
183 }
184 
185 
186 Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler()
187 {
188  return this;
189 }
190 
191 // XInteractionHandler
192 
193 void CommandEnvironmentImpl::handle(
194  Reference<task::XInteractionRequest> const & xRequest )
195 {
196  Any request( xRequest->getRequest() );
197  OSL_ASSERT( request.getValueTypeClass() == TypeClass_EXCEPTION );
198  dp_misc::TRACE("[unopkg_cmdenv.cxx] incoming request:\n"
199  + ::comphelper::anyToString(request) + "\n\n");
200 
201  // selections:
202  bool approve = false;
203  bool abort = false;
204 
205  lang::WrappedTargetException wtExc;
206  deployment::LicenseException licExc;
207  deployment::InstallException instExc;
208  deployment::PlatformException platExc;
209 
210  if (request >>= wtExc) {
211  // ignore intermediate errors of legacy packages, i.e.
212  // former pkgchk behaviour:
213  const Reference<deployment::XPackage> xPackage(
214  wtExc.Context, UNO_QUERY );
215  OSL_ASSERT( xPackage.is() );
216  if (xPackage.is()) {
217  const Reference<deployment::XPackageTypeInfo> xPackageType(
218  xPackage->getPackageType() );
219  OSL_ASSERT( xPackageType.is() );
220  if (xPackageType.is()) {
221  approve = (xPackage->isBundle() &&
222  xPackageType->getMediaType().match(
223  "application/vnd.sun.star.legacy-package-bundle") );
224  }
225  }
226  abort = !approve;
227  if (abort) {
228  // notify cause as error:
229  request = wtExc.TargetException;
230  }
231  else {
232  // handable deployment error signalled, e.g.
233  // bundle item registration failed, notify as warning:
234  update_( wtExc.TargetException );
235  }
236  }
237  else if (request >>= licExc)
238  {
239  if ( !m_option_suppress_license )
240  printLicense(licExc.ExtensionName, licExc.Text, approve, abort);
241  else
242  {
243  approve = true;
244  abort = false;
245  }
246  }
247  else if (request >>= instExc)
248  {
249  //Only if the unopgk was started with gui + extension then the user is asked.
250  //In console mode there is no asking.
251  approve = true;
252  }
253  else if (request >>= platExc)
254  {
255  OUString sMsg(DpResId(RID_STR_UNSUPPORTED_PLATFORM));
256  sMsg = sMsg.replaceAll("%Name", platExc.package->getDisplayName());
257  dp_misc::writeConsole("\n" + sMsg + "\n\n");
258  approve = true;
259  }
260  else {
261  deployment::VersionException nc_exc;
262  if (request >>= nc_exc) {
263  approve = m_option_force_overwrite ||
264  (::dp_misc::compareVersions(nc_exc.NewVersion, nc_exc.Deployed->getVersion())
265  == ::dp_misc::GREATER);
266  abort = !approve;
267  }
268  else
269  return; // unknown request => no selection at all
270  }
271 
272  if (abort && m_option_verbose)
273  {
274  OUString msg = ::comphelper::anyToString(request);
275  dp_misc::writeConsoleError("\nERROR: " + msg + "\n");
276  }
277 
278  // select:
279  const css::uno::Sequence<css::uno::Reference<css::task::XInteractionContinuation>> xIC = xRequest->getContinuations();
280  for ( auto const& rCont : xIC )
281  {
282  if (approve) {
283  Reference<task::XInteractionApprove> xInteractionApprove(
284  rCont, UNO_QUERY );
285  if (xInteractionApprove.is()) {
286  xInteractionApprove->select();
287  break;
288  }
289  }
290  else if (abort) {
291  Reference<task::XInteractionAbort> xInteractionAbort(
292  rCont, UNO_QUERY );
293  if (xInteractionAbort.is()) {
294  xInteractionAbort->select();
295  break;
296  }
297  }
298  }
299 }
300 
301 // XProgressHandler
302 
303 void CommandEnvironmentImpl::push( Any const & Status )
304 {
305  update_( Status );
306  OSL_ASSERT( m_logLevel >= 0 );
307  ++m_logLevel;
308  if (m_xLogFile.is())
309  m_xLogFile->push( Status );
310 }
311 
312 
313 void CommandEnvironmentImpl::update_( Any const & Status )
314 {
315  if (! Status.hasValue())
316  return;
317  bool bUseErr = false;
318  OUString msg;
319  if (Status >>= msg) {
320  if (! m_option_verbose)
321  return;
322  }
323  else {
324  OUStringBuffer buf;
325  buf.append( "WARNING: " );
326  deployment::DeploymentException dp_exc;
327  if (Status >>= dp_exc) {
328  buf.append( dp_exc.Message );
329  buf.append( ", Cause: " );
330  buf.append( ::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(msg + "\n");
349  else
350  dp_misc::writeConsole(msg + "\n");
351 }
352 
353 
354 void CommandEnvironmentImpl::update( Any const & Status )
355 {
356  update_( Status );
357  if (m_xLogFile.is())
358  m_xLogFile->update( Status );
359 }
360 
361 
362 void 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 
373 namespace unopkg {
374 
375 
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: */
Reference< XCommandEnvironment > createCmdEnv(Reference< XComponentContext > const &xContext, bool option_force_overwrite, bool option_verbose, bool option_suppress_license)
bool update()
Definition: updater.cxx:284
sal_Int64 n
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(OUString const &version1, OUString const &version2)
Definition: dp_version.cxx:41
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)
void writeConsole(OUString const &sText)
writes the argument string to the console.
Definition: dp_misc.cxx:465
Reference< XComponentContext > const m_xComponentContext
#define TOOLS_WARN_EXCEPTION(area, stream)
static OUString getUILocale()
void writeConsoleError(OUString const &sText)
writes the argument to the console using the error stream.
Definition: dp_misc.cxx:470
const LanguageTag & getLocale()
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2105
void TRACE(OUString const &sText)
print the text to the console in a debug build.
Definition: dp_misc.cxx:488
OUString DpResId(const char *pId)
Definition: dp_shared.hxx:37
OUString readConsole()
reads from the console.
Definition: dp_misc.cxx:475
OUString anyToString(uno::Any const &value)