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