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 "../../deployment/gui/dp_gui.hrc"
28 #include "../../deployment/gui/dp_gui_shared.hxx"
29 #include "unopkg_shared.h"
30 #include "osl/thread.h"
31 #include "rtl/memory.h"
32 #include "tools/string.hxx"
33 #include "tools/resmgr.hxx"
34 #include "cppuhelper/implbase3.hxx"
35 #include "cppuhelper/exc_hlp.hxx"
36 #include "comphelper/anytostring.hxx"
37 #include "unotools/configmgr.hxx"
38 #include "com/sun/star/lang/WrappedTargetException.hpp"
39 #include "com/sun/star/task/XInteractionAbort.hpp"
40 #include "com/sun/star/task/XInteractionApprove.hpp"
41 #include "com/sun/star/deployment/InstallException.hpp"
42 #include "com/sun/star/container/ElementExistException.hpp"
43 #include "com/sun/star/deployment/LicenseException.hpp"
44 #include "com/sun/star/deployment/VersionException.hpp"
45 #include "com/sun/star/deployment/PlatformException.hpp"
46 #include "com/sun/star/i18n/XCollator.hpp"
47 #include "com/sun/star/i18n/CollatorOptions.hpp"
48
49 #include <stdio.h>
50 #include "deployment.hrc"
51 #include "dp_version.hxx"
52
53 namespace css = ::com::sun::star;
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::ucb;
56 using namespace ::com::sun::star::uno;
57 using namespace ::unopkg;
58 using ::rtl::OUString;
59
60
61 namespace {
62
63 //==============================================================================
64 struct OfficeLocale :
65 public rtl::StaticWithInit<const lang::Locale, OfficeLocale> {
operator ()__anona09d055a0111::OfficeLocale66 const lang::Locale operator () () {
67 OUString slang;
68 if (! (::utl::ConfigManager::GetDirectConfigProperty(
69 ::utl::ConfigManager::LOCALE ) >>= slang))
70 throw RuntimeException( OUSTR("Cannot determine language!"), 0 );
71 return toLocale(slang);
72 }
73 };
74
75 //==============================================================================
76 class CommandEnvironmentImpl
77 : public ::cppu::WeakImplHelper3< XCommandEnvironment,
78 task::XInteractionHandler,
79 XProgressHandler >
80 {
81 sal_Int32 m_logLevel;
82 bool m_option_force_overwrite;
83 bool m_option_verbose;
84 Reference< XComponentContext > m_xComponentContext;
85 Reference< XProgressHandler > m_xLogFile;
86
87 void update_( Any const & Status );
88 void printLicense(const OUString & sName,const OUString& sLicense,
89 bool & accept, bool & decline);
90
91 public:
92 virtual ~CommandEnvironmentImpl();
93 CommandEnvironmentImpl(
94 Reference<XComponentContext> const & xComponentContext,
95 OUString const & log_file,
96 bool option_force_overwrite,
97 bool option_verbose);
98
99 // XCommandEnvironment
100 virtual Reference< task::XInteractionHandler > SAL_CALL
101 getInteractionHandler();
102 virtual Reference< XProgressHandler > SAL_CALL getProgressHandler();
103
104 // XInteractionHandler
105 virtual void SAL_CALL handle(
106 Reference< task::XInteractionRequest > const & xRequest );
107
108 // XProgressHandler
109 virtual void SAL_CALL push( Any const & Status );
110 virtual void SAL_CALL update( Any const & Status );
111 virtual void SAL_CALL pop();
112 };
113
114
115 //______________________________________________________________________________
CommandEnvironmentImpl(Reference<XComponentContext> const & xComponentContext,OUString const & log_file,bool option_force_overwrite,bool option_verbose)116 CommandEnvironmentImpl::CommandEnvironmentImpl(
117 Reference<XComponentContext> const & xComponentContext,
118 OUString const & log_file,
119 bool option_force_overwrite,
120 bool option_verbose)
121 : m_logLevel(0),
122 m_option_force_overwrite( option_force_overwrite ),
123 m_option_verbose( option_verbose ),
124 m_xComponentContext(xComponentContext)
125 {
126 if (log_file.getLength() > 0) {
127 const Any logfile(log_file);
128 m_xLogFile.set(
129 xComponentContext->getServiceManager()
130 ->createInstanceWithArgumentsAndContext(
131 OUSTR("com.sun.star.comp.deployment.ProgressLog"),
132 Sequence<Any>( &logfile, 1 ), xComponentContext ),
133 UNO_QUERY_THROW );
134 }
135 }
136
137 //______________________________________________________________________________
~CommandEnvironmentImpl()138 CommandEnvironmentImpl::~CommandEnvironmentImpl()
139 {
140 try {
141 Reference< lang::XComponent > xComp( m_xLogFile, UNO_QUERY );
142 if (xComp.is())
143 xComp->dispose();
144 }
145 catch (RuntimeException & exc) {
146 (void) exc;
147 OSL_ENSURE( 0, ::rtl::OUStringToOString(
148 exc.Message, osl_getThreadTextEncoding() ).getStr() );
149 }
150 }
151
152 //May throw exceptions
printLicense(const OUString & sName,const OUString & sLicense,bool & accept,bool & decline)153 void CommandEnvironmentImpl::printLicense(
154 const OUString & sName, const OUString& sLicense, bool & accept, bool &decline)
155 {
156 ResMgr * pResMgr = DeploymentResMgr::get();
157 String s1tmp(ResId(RID_STR_UNOPKG_ACCEPT_LIC_1, *pResMgr));
158 s1tmp.SearchAndReplaceAllAscii( "$NAME", sName );
159 OUString s1(s1tmp);
160 OUString s2 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_2, *pResMgr));
161 OUString s3 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_3, *pResMgr));
162 OUString s4 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_4, *pResMgr));
163 OUString sYES = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_YES, *pResMgr));
164 OUString sY = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_Y, *pResMgr));
165 OUString sNO = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_NO, *pResMgr));
166 OUString sN = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_N, *pResMgr));
167
168 OUString sNewLine(RTL_CONSTASCII_USTRINGPARAM("\n"));
169
170 dp_misc::writeConsole(sNewLine + sNewLine + s1 + sNewLine + sNewLine);
171 dp_misc::writeConsole(sLicense + sNewLine + sNewLine);
172 dp_misc::writeConsole(s2 + sNewLine);
173 dp_misc::writeConsole(s3);
174
175 //the user may enter "yes" or "no", we compare in a case insensitive way
176 Reference< css::i18n::XCollator > xCollator(
177 m_xComponentContext->getServiceManager()
178 ->createInstanceWithContext(
179 OUSTR("com.sun.star.i18n.Collator"),m_xComponentContext),
180 UNO_QUERY_THROW );
181 xCollator->loadDefaultCollator(OfficeLocale::get(),
182 css::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE);
183
184 do
185 {
186 OUString sAnswer = dp_misc::readConsole();
187 if (xCollator->compareString(sAnswer, sYES) == 0
188 || xCollator->compareString(sAnswer, sY) == 0)
189 {
190 accept = true;
191 break;
192 }
193 else if(xCollator->compareString(sAnswer, sNO) == 0
194 || xCollator->compareString(sAnswer, sN) == 0)
195 {
196 decline = true;
197 break;
198 }
199 else
200 {
201 dp_misc::writeConsole(sNewLine + sNewLine + s4 + sNewLine);
202 }
203 }
204 while(true);
205 }
206
207 // XCommandEnvironment
208 //______________________________________________________________________________
209 Reference< task::XInteractionHandler >
getInteractionHandler()210 CommandEnvironmentImpl::getInteractionHandler()
211 {
212 return this;
213 }
214
215 //______________________________________________________________________________
getProgressHandler()216 Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler()
217 {
218 return this;
219 }
220
221 // XInteractionHandler
222 //______________________________________________________________________________
handle(Reference<task::XInteractionRequest> const & xRequest)223 void CommandEnvironmentImpl::handle(
224 Reference<task::XInteractionRequest> const & xRequest )
225 {
226 Any request( xRequest->getRequest() );
227 OSL_ASSERT( request.getValueTypeClass() == TypeClass_EXCEPTION );
228 dp_misc::TRACE(OUSTR("[unopkg_cmdenv.cxx] incoming request:\n")
229 + ::comphelper::anyToString(request) + OUSTR("\n\n"));
230
231 // selections:
232 bool approve = false;
233 bool abort = false;
234
235 lang::WrappedTargetException wtExc;
236 deployment::LicenseException licExc;
237 deployment::InstallException instExc;
238 deployment::PlatformException platExc;
239 deployment::VersionException verExc;
240
241
242 bool bLicenseException = false;
243 if (request >>= wtExc) {
244 // ignore intermediate errors of legacy packages, i.e.
245 // former pkgchk behaviour:
246 const Reference<deployment::XPackage> xPackage(
247 wtExc.Context, UNO_QUERY );
248 OSL_ASSERT( xPackage.is() );
249 if (xPackage.is()) {
250 const Reference<deployment::XPackageTypeInfo> xPackageType(
251 xPackage->getPackageType() );
252 OSL_ASSERT( xPackageType.is() );
253 if (xPackageType.is()) {
254 approve = (xPackage->isBundle() &&
255 xPackageType->getMediaType().matchAsciiL(
256 RTL_CONSTASCII_STRINGPARAM(
257 "application/"
258 "vnd.sun.star.legacy-package-bundle") ));
259 }
260 }
261 abort = !approve;
262 if (abort) {
263 // notify cause as error:
264 request = wtExc.TargetException;
265 }
266 else {
267 // handable deployment error signaled, e.g.
268 // bundle item registration failed, notify as warning:
269 update_( wtExc.TargetException );
270 }
271 }
272 else if (request >>= licExc)
273 {
274 printLicense(licExc.ExtensionName, licExc.Text, approve, abort);
275 }
276 else if (request >>= instExc)
277 {
278 //Only if the unopgk was started with gui + extension then the user is asked.
279 //In console mode there is no asking.
280 approve = true;
281 }
282 else if (request >>= platExc)
283 {
284 String sMsg(ResId(RID_STR_UNSUPPORTED_PLATFORM, *dp_gui::DeploymentGuiResMgr::get()));
285 sMsg.SearchAndReplaceAllAscii("%Name", platExc.package->getDisplayName());
286 dp_misc::writeConsole(OUSTR("\n") + sMsg + OUSTR("\n\n"));
287 approve = true;
288 }
289 else {
290 deployment::VersionException nc_exc;
291 if (request >>= nc_exc) {
292 approve = m_option_force_overwrite ||
293 (::dp_misc::compareVersions(nc_exc.NewVersion, nc_exc.Deployed->getVersion())
294 == ::dp_misc::GREATER);
295 abort = !approve;
296 }
297 else
298 return; // unknown request => no selection at all
299 }
300
301 //In case of a user declining a license abort is true but this is intended,
302 //therefore no logging
303 if (abort && m_option_verbose && !bLicenseException)
304 {
305 OUString msg = ::comphelper::anyToString(request);
306 dp_misc::writeConsoleError(
307 OUSTR("\nERROR: ") + msg + OUSTR("\n"));
308 }
309
310 // select:
311 Sequence< Reference<task::XInteractionContinuation> > conts(
312 xRequest->getContinuations() );
313 Reference<task::XInteractionContinuation> const * pConts =
314 conts.getConstArray();
315 sal_Int32 len = conts.getLength();
316 for ( sal_Int32 pos = 0; pos < len; ++pos )
317 {
318 if (approve) {
319 Reference<task::XInteractionApprove> xInteractionApprove(
320 pConts[ pos ], UNO_QUERY );
321 if (xInteractionApprove.is()) {
322 xInteractionApprove->select();
323 break;
324 }
325 }
326 else if (abort) {
327 Reference<task::XInteractionAbort> xInteractionAbort(
328 pConts[ pos ], UNO_QUERY );
329 if (xInteractionAbort.is()) {
330 xInteractionAbort->select();
331 break;
332 }
333 }
334 }
335 }
336
337 // XProgressHandler
338 //______________________________________________________________________________
push(Any const & Status)339 void CommandEnvironmentImpl::push( Any const & Status )
340 {
341 update_( Status );
342 OSL_ASSERT( m_logLevel >= 0 );
343 ++m_logLevel;
344 if (m_xLogFile.is())
345 m_xLogFile->push( Status );
346 }
347
348 //______________________________________________________________________________
update_(Any const & Status)349 void CommandEnvironmentImpl::update_( Any const & Status )
350 {
351 if (! Status.hasValue())
352 return;
353 bool bUseErr = false;
354 OUString msg;
355 if (Status >>= msg) {
356 if (! m_option_verbose)
357 return;
358 }
359 else {
360 ::rtl::OUStringBuffer buf;
361 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("WARNING: ") );
362 deployment::DeploymentException dp_exc;
363 if (Status >>= dp_exc) {
364 buf.append( dp_exc.Message );
365 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", Cause: ") );
366 buf.append( ::comphelper::anyToString(dp_exc.Cause) );
367 }
368 else {
369 buf.append( ::comphelper::anyToString(Status) );
370 }
371 msg = buf.makeStringAndClear();
372 bUseErr = true;
373 }
374 OSL_ASSERT( m_logLevel >= 0 );
375 for ( sal_Int32 n = 0; n < m_logLevel; ++n )
376 {
377 if (bUseErr)
378 dp_misc::writeConsoleError(" ");
379 else
380 dp_misc::writeConsole(" ");
381 }
382
383 if (bUseErr)
384 dp_misc::writeConsoleError(msg + OUSTR("\n"));
385 else
386 dp_misc::writeConsole(msg + OUSTR("\n"));
387 }
388
389 //______________________________________________________________________________
update(Any const & Status)390 void CommandEnvironmentImpl::update( Any const & Status )
391 {
392 update_( Status );
393 if (m_xLogFile.is())
394 m_xLogFile->update( Status );
395 }
396
397 //______________________________________________________________________________
pop()398 void CommandEnvironmentImpl::pop()
399 {
400 OSL_ASSERT( m_logLevel > 0 );
401 --m_logLevel;
402 if (m_xLogFile.is())
403 m_xLogFile->pop();
404 }
405
406
407 } // anon namespace
408
409 namespace unopkg {
410
411 //==============================================================================
createCmdEnv(Reference<XComponentContext> const & xContext,OUString const & logFile,bool option_force_overwrite,bool option_verbose)412 Reference< XCommandEnvironment > createCmdEnv(
413 Reference< XComponentContext > const & xContext,
414 OUString const & logFile,
415 bool option_force_overwrite,
416 bool option_verbose)
417 {
418 return new CommandEnvironmentImpl(
419 xContext, logFile, option_force_overwrite, option_verbose);
420 }
421 } // unopkg
422