/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_desktop.hxx" #include "../../deployment/gui/dp_gui.hrc" #include "../../deployment/gui/dp_gui_shared.hxx" #include "unopkg_shared.h" #include "osl/thread.h" #include "rtl/memory.h" #include "tools/string.hxx" #include "tools/resmgr.hxx" #include "cppuhelper/implbase3.hxx" #include "cppuhelper/exc_hlp.hxx" #include "comphelper/anytostring.hxx" #include "unotools/configmgr.hxx" #include "com/sun/star/lang/WrappedTargetException.hpp" #include "com/sun/star/task/XInteractionAbort.hpp" #include "com/sun/star/task/XInteractionApprove.hpp" #include "com/sun/star/deployment/InstallException.hpp" #include "com/sun/star/container/ElementExistException.hpp" #include "com/sun/star/deployment/LicenseException.hpp" #include "com/sun/star/deployment/VersionException.hpp" #include "com/sun/star/deployment/PlatformException.hpp" #include "com/sun/star/i18n/XCollator.hpp" #include "com/sun/star/i18n/CollatorOptions.hpp" #include #include "deployment.hrc" #include "dp_version.hxx" namespace css = ::com::sun::star; using namespace ::com::sun::star; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::uno; using namespace ::unopkg; using ::rtl::OUString; namespace { //============================================================================== struct OfficeLocale : public rtl::StaticWithInit { const lang::Locale operator () () { OUString slang; if (! (::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE ) >>= slang)) throw RuntimeException( OUSTR("Cannot determine language!"), 0 ); return toLocale(slang); } }; //============================================================================== class CommandEnvironmentImpl : public ::cppu::WeakImplHelper3< XCommandEnvironment, task::XInteractionHandler, XProgressHandler > { sal_Int32 m_logLevel; bool m_option_force_overwrite; bool m_option_verbose; Reference< XComponentContext > m_xComponentContext; Reference< XProgressHandler > m_xLogFile; void update_( Any const & Status ) throw (RuntimeException); void printLicense(const OUString & sName,const OUString& sLicense, bool & accept, bool & decline); public: virtual ~CommandEnvironmentImpl(); CommandEnvironmentImpl( Reference const & xComponentContext, OUString const & log_file, bool option_force_overwrite, bool option_verbose); // XCommandEnvironment virtual Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler() throw (RuntimeException); virtual Reference< XProgressHandler > SAL_CALL getProgressHandler() throw (RuntimeException); // XInteractionHandler virtual void SAL_CALL handle( Reference< task::XInteractionRequest > const & xRequest ) throw (RuntimeException); // XProgressHandler virtual void SAL_CALL push( Any const & Status ) throw (RuntimeException); virtual void SAL_CALL update( Any const & Status ) throw (RuntimeException); virtual void SAL_CALL pop() throw (RuntimeException); }; //______________________________________________________________________________ CommandEnvironmentImpl::CommandEnvironmentImpl( Reference const & xComponentContext, OUString const & log_file, bool option_force_overwrite, bool option_verbose) : m_logLevel(0), m_option_force_overwrite( option_force_overwrite ), m_option_verbose( option_verbose ), m_xComponentContext(xComponentContext) { if (log_file.getLength() > 0) { const Any logfile(log_file); m_xLogFile.set( xComponentContext->getServiceManager() ->createInstanceWithArgumentsAndContext( OUSTR("com.sun.star.comp.deployment.ProgressLog"), Sequence( &logfile, 1 ), xComponentContext ), UNO_QUERY_THROW ); } } //______________________________________________________________________________ CommandEnvironmentImpl::~CommandEnvironmentImpl() { try { Reference< lang::XComponent > xComp( m_xLogFile, UNO_QUERY ); if (xComp.is()) xComp->dispose(); } catch (RuntimeException & exc) { (void) exc; OSL_ENSURE( 0, ::rtl::OUStringToOString( exc.Message, osl_getThreadTextEncoding() ).getStr() ); } } //May throw exceptions void CommandEnvironmentImpl::printLicense( const OUString & sName, const OUString& sLicense, bool & accept, bool &decline) { ResMgr * pResMgr = DeploymentResMgr::get(); String s1tmp(ResId(RID_STR_UNOPKG_ACCEPT_LIC_1, *pResMgr)); s1tmp.SearchAndReplaceAllAscii( "$NAME", sName ); OUString s1(s1tmp); OUString s2 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_2, *pResMgr)); OUString s3 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_3, *pResMgr)); OUString s4 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_4, *pResMgr)); OUString sYES = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_YES, *pResMgr)); OUString sY = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_Y, *pResMgr)); OUString sNO = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_NO, *pResMgr)); OUString sN = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_N, *pResMgr)); OUString sNewLine(RTL_CONSTASCII_USTRINGPARAM("\n")); dp_misc::writeConsole(sNewLine + sNewLine + s1 + sNewLine + sNewLine); dp_misc::writeConsole(sLicense + sNewLine + sNewLine); dp_misc::writeConsole(s2 + sNewLine); dp_misc::writeConsole(s3); //the user may enter "yes" or "no", we compare in a case insensitive way Reference< css::i18n::XCollator > xCollator( m_xComponentContext->getServiceManager() ->createInstanceWithContext( OUSTR("com.sun.star.i18n.Collator"),m_xComponentContext), UNO_QUERY_THROW ); xCollator->loadDefaultCollator(OfficeLocale::get(), css::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE); do { OUString sAnswer = dp_misc::readConsole(); if (xCollator->compareString(sAnswer, sYES) == 0 || xCollator->compareString(sAnswer, sY) == 0) { accept = true; break; } else if(xCollator->compareString(sAnswer, sNO) == 0 || xCollator->compareString(sAnswer, sN) == 0) { decline = true; break; } else { dp_misc::writeConsole(sNewLine + sNewLine + s4 + sNewLine); } } while(true); } // XCommandEnvironment //______________________________________________________________________________ Reference< task::XInteractionHandler > CommandEnvironmentImpl::getInteractionHandler() throw (RuntimeException) { return this; } //______________________________________________________________________________ Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler() throw (RuntimeException) { return this; } // XInteractionHandler //______________________________________________________________________________ void CommandEnvironmentImpl::handle( Reference const & xRequest ) throw (RuntimeException) { Any request( xRequest->getRequest() ); OSL_ASSERT( request.getValueTypeClass() == TypeClass_EXCEPTION ); dp_misc::TRACE(OUSTR("[unopkg_cmdenv.cxx] incoming request:\n") + ::comphelper::anyToString(request) + OUSTR("\n\n")); // selections: bool approve = false; bool abort = false; lang::WrappedTargetException wtExc; deployment::LicenseException licExc; deployment::InstallException instExc; deployment::PlatformException platExc; deployment::VersionException verExc; bool bLicenseException = false; if (request >>= wtExc) { // ignore intermediate errors of legacy packages, i.e. // former pkgchk behaviour: const Reference xPackage( wtExc.Context, UNO_QUERY ); OSL_ASSERT( xPackage.is() ); if (xPackage.is()) { const Reference xPackageType( xPackage->getPackageType() ); OSL_ASSERT( xPackageType.is() ); if (xPackageType.is()) { approve = (xPackage->isBundle() && xPackageType->getMediaType().matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/" "vnd.sun.star.legacy-package-bundle") )); } } abort = !approve; if (abort) { // notify cause as error: request = wtExc.TargetException; } else { // handable deployment error signaled, e.g. // bundle item registration failed, notify as warning: update_( wtExc.TargetException ); } } else if (request >>= licExc) { printLicense(licExc.ExtensionName, licExc.Text, approve, abort); } else if (request >>= instExc) { //Only if the unopgk was started with gui + extension then the user is asked. //In console mode there is no asking. approve = true; } else if (request >>= platExc) { String sMsg(ResId(RID_STR_UNSUPPORTED_PLATFORM, *dp_gui::DeploymentGuiResMgr::get())); sMsg.SearchAndReplaceAllAscii("%Name", platExc.package->getDisplayName()); dp_misc::writeConsole(OUSTR("\n") + sMsg + OUSTR("\n\n")); approve = true; } else { deployment::VersionException nc_exc; if (request >>= nc_exc) { approve = m_option_force_overwrite || (::dp_misc::compareVersions(nc_exc.NewVersion, nc_exc.Deployed->getVersion()) == ::dp_misc::GREATER); abort = !approve; } else return; // unknown request => no selection at all } //In case of a user declining a license abort is true but this is intended, //therefore no logging if (abort && m_option_verbose && !bLicenseException) { OUString msg = ::comphelper::anyToString(request); dp_misc::writeConsoleError( OUSTR("\nERROR: ") + msg + OUSTR("\n")); } // select: Sequence< Reference > conts( xRequest->getContinuations() ); Reference const * pConts = conts.getConstArray(); sal_Int32 len = conts.getLength(); for ( sal_Int32 pos = 0; pos < len; ++pos ) { if (approve) { Reference xInteractionApprove( pConts[ pos ], UNO_QUERY ); if (xInteractionApprove.is()) { xInteractionApprove->select(); break; } } else if (abort) { Reference xInteractionAbort( pConts[ pos ], UNO_QUERY ); if (xInteractionAbort.is()) { xInteractionAbort->select(); break; } } } } // XProgressHandler //______________________________________________________________________________ void CommandEnvironmentImpl::push( Any const & Status ) throw (RuntimeException) { update_( Status ); OSL_ASSERT( m_logLevel >= 0 ); ++m_logLevel; if (m_xLogFile.is()) m_xLogFile->push( Status ); } //______________________________________________________________________________ void CommandEnvironmentImpl::update_( Any const & Status ) throw (RuntimeException) { if (! Status.hasValue()) return; bool bUseErr = false; OUString msg; if (Status >>= msg) { if (! m_option_verbose) return; } else { ::rtl::OUStringBuffer buf; buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("WARNING: ") ); deployment::DeploymentException dp_exc; if (Status >>= dp_exc) { buf.append( dp_exc.Message ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", Cause: ") ); buf.append( ::comphelper::anyToString(dp_exc.Cause) ); } else { buf.append( ::comphelper::anyToString(Status) ); } msg = buf.makeStringAndClear(); bUseErr = true; } OSL_ASSERT( m_logLevel >= 0 ); for ( sal_Int32 n = 0; n < m_logLevel; ++n ) { if (bUseErr) dp_misc::writeConsoleError(" "); else dp_misc::writeConsole(" "); } if (bUseErr) dp_misc::writeConsoleError(msg + OUSTR("\n")); else dp_misc::writeConsole(msg + OUSTR("\n")); } //______________________________________________________________________________ void CommandEnvironmentImpl::update( Any const & Status ) throw (RuntimeException) { update_( Status ); if (m_xLogFile.is()) m_xLogFile->update( Status ); } //______________________________________________________________________________ void CommandEnvironmentImpl::pop() throw (RuntimeException) { OSL_ASSERT( m_logLevel > 0 ); --m_logLevel; if (m_xLogFile.is()) m_xLogFile->pop(); } } // anon namespace namespace unopkg { //============================================================================== Reference< XCommandEnvironment > createCmdEnv( Reference< XComponentContext > const & xContext, OUString const & logFile, bool option_force_overwrite, bool option_verbose) { return new CommandEnvironmentImpl( xContext, logFile, option_force_overwrite, option_verbose); } } // unopkg