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_shared.hxx>
23 #include "unopkg_shared.h"
24 #include <osl/thread.h>
25 #include <sal/log.hxx>
26 #include <unotools/resmgr.hxx>
27 #include <cppuhelper/implbase.hxx>
28 #include <cppuhelper/exc_hlp.hxx>
30 #include <tools/diagnose_ex.h>
31 #include <unotools/configmgr.hxx>
32 #include <com/sun/star/lang/WrappedTargetException.hpp>
33 #include <com/sun/star/task/XInteractionAbort.hpp>
34 #include <com/sun/star/task/XInteractionApprove.hpp>
35 #include <com/sun/star/deployment/DeploymentException.hpp>
36 #include <com/sun/star/deployment/InstallException.hpp>
37 #include <com/sun/star/container/ElementExistException.hpp>
38 #include <com/sun/star/deployment/LicenseException.hpp>
39 #include <com/sun/star/deployment/VersionException.hpp>
40 #include <com/sun/star/deployment/PlatformException.hpp>
41 #include <com/sun/star/i18n/Collator.hpp>
42 #include <com/sun/star/i18n/CollatorOptions.hpp>
43 
44 #include <stdio.h>
45 #include <dp_version.hxx>
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::ucb;
49 using namespace ::com::sun::star::uno;
50 using namespace ::unopkg;
51 
52 
53 namespace {
54 
55 
56 class 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;
67 
69  void update_( Any const & Status );
70  void printLicense(const OUString & sName,const OUString& sLicense,
71  bool & accept, bool & decline);
72 
73 public:
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
82  virtual Reference< task::XInteractionHandler > SAL_CALL
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 
97 CommandEnvironmentImpl::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 
117 CommandEnvironmentImpl::~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
130 void CommandEnvironmentImpl::printLicense(
131  const OUString & sName, const OUString& 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(sNewLine + sNewLine + s1 + sNewLine + sNewLine);
146  dp_misc::writeConsole(sLicense + sNewLine + sNewLine);
147  dp_misc::writeConsole(s2 + sNewLine);
149 
150  //the user may enter "yes" or "no", we compare in a case insensitive way
151  Reference< css::i18n::XCollator > xCollator =
152  css::i18n::Collator::create( m_xComponentContext );
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(sNewLine + sNewLine + s4 + sNewLine);
175  }
176  }
177  while(true);
178 }
179 
180 // XCommandEnvironment
181 
182 Reference< task::XInteractionHandler >
183 CommandEnvironmentImpl::getInteractionHandler()
184 {
185  return this;
186 }
187 
188 
189 Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler()
190 {
191  return this;
192 }
193 
194 // XInteractionHandler
195 
196 void 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("\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())
268  == ::dp_misc::GREATER);
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("\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 
306 void 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 
316 void 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;
328  buf.append( "WARNING: " );
329  deployment::DeploymentException dp_exc;
330  if (Status >>= dp_exc) {
331  buf.append( dp_exc.Message );
332  buf.append( ", Cause: " );
333  buf.append( ::comphelper::anyToString(dp_exc.Cause) );
334  }
335  else {
336  buf.append( ::comphelper::anyToString(Status) );
337  }
338  msg = buf.makeStringAndClear();
339  bUseErr = true;
340  }
341  OSL_ASSERT( m_logLevel >= 0 );
342  for ( sal_Int32 n = 0; n < m_logLevel; ++n )
343  {
344  if (bUseErr)
346  else
348  }
349 
350  if (bUseErr)
351  dp_misc::writeConsoleError(msg + "\n");
352  else
353  dp_misc::writeConsole(msg + "\n");
354 }
355 
356 
357 void CommandEnvironmentImpl::update( Any const & Status )
358 {
359  update_( Status );
360  if (m_xLogFile.is())
361  m_xLogFile->update( Status );
362 }
363 
364 
365 void CommandEnvironmentImpl::pop()
366 {
367  OSL_ASSERT( m_logLevel > 0 );
368  --m_logLevel;
369  if (m_xLogFile.is())
370  m_xLogFile->pop();
371 }
372 
373 
374 } // anon namespace
375 
376 namespace unopkg {
377 
378 
381  bool option_force_overwrite,
382  bool option_verbose,
383  bool option_suppress_license)
384 {
385  return new CommandEnvironmentImpl(
386  xContext, option_force_overwrite, option_verbose, option_suppress_license);
387 }
388 } // unopkg
389 
390 /* 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
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(OUString const &version1, OUString const &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)
void writeConsole(OUString const &sText)
writes the argument string to the console.
Definition: dp_misc.cxx:484
#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:493
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:1858
void TRACE(OUString const &sText)
print the text to the console in a debug build.
Definition: dp_misc.cxx:527
OUString DpResId(const char *pId)
Definition: dp_shared.hxx:38
OUString readConsole()
reads from the console.
Definition: dp_misc.cxx:502
OUString anyToString(uno::Any const &value)