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