blob: 8ea1e8b328257c270d1ecd946bac2ab3c0d620e5 [file] [log] [blame]
/**************************************************************
*
* 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