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> { 66 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 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 > 212 CommandEnvironmentImpl::getInteractionHandler() throw (RuntimeException) 213 { 214 return this; 215 } 216 217 //______________________________________________________________________________ 218 Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler() 219 throw (RuntimeException) 220 { 221 return this; 222 } 223 224 // XInteractionHandler 225 //______________________________________________________________________________ 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 signalled, 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 we 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //============================================================================== 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