| /************************************************************** |
| * |
| * 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 <stdio.h> |
| #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, OfficeLocale> { |
| 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<XComponentContext> 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<XComponentContext> 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<Any>( &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<task::XInteractionRequest> 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<deployment::XPackage> xPackage( |
| wtExc.Context, UNO_QUERY ); |
| OSL_ASSERT( xPackage.is() ); |
| if (xPackage.is()) { |
| const Reference<deployment::XPackageTypeInfo> 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 signalled, 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 we 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<task::XInteractionContinuation> > conts( |
| xRequest->getContinuations() ); |
| Reference<task::XInteractionContinuation> const * pConts = |
| conts.getConstArray(); |
| sal_Int32 len = conts.getLength(); |
| for ( sal_Int32 pos = 0; pos < len; ++pos ) |
| { |
| if (approve) { |
| Reference<task::XInteractionApprove> xInteractionApprove( |
| pConts[ pos ], UNO_QUERY ); |
| if (xInteractionApprove.is()) { |
| xInteractionApprove->select(); |
| break; |
| } |
| } |
| else if (abort) { |
| Reference<task::XInteractionAbort> 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 |
| |