diff options
Diffstat (limited to 'desktop/source/pkgchk')
-rw-r--r-- | desktop/source/pkgchk/unopkg/makefile.mk | 106 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_app.cxx | 512 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx | 445 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_main.c | 39 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_main.h | 46 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_misc.cxx | 509 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/unopkg_shared.h | 186 | ||||
-rw-r--r-- | desktop/source/pkgchk/unopkg/version.map | 38 |
8 files changed, 1881 insertions, 0 deletions
diff --git a/desktop/source/pkgchk/unopkg/makefile.mk b/desktop/source/pkgchk/unopkg/makefile.mk new file mode 100644 index 000000000000..3562fad961d9 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/makefile.mk @@ -0,0 +1,106 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.17 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. + +PRJNAME = desktop +TARGET = unopkg +.IF "$(GUI)" == "OS2" +TARGETTYPE = CUI +.ELSE +TARGETTYPE = GUI +.ENDIF +ENABLE_EXCEPTIONS = TRUE +LIBTARGET=NO + +PRJINC += ..$/..$/deployment ..$/.. +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +APP1TARGET = so$/unopkg +APP1OBJS = $(OBJFILES) +APP1STDLIBS = $(SALLIB) $(UNOPKGAPPLIB) +APP1DEPN = $(SHL1TARGETN) +APP1NOSAL = TRUE +APP1RPATH = BRAND +.IF "$(OS)" == "WNT" +APP1ICON = $(SOLARRESDIR)$/icons/so9_main_app.ico +APP1LINKRES = $(MISC)$/$(TARGET)1.res +.ENDIF + +APP2TARGET = unopkg +APP2OBJS = $(OBJFILES) +APP2STDLIBS = $(SALLIB) $(UNOPKGAPPLIB) +APP2DEPN = $(SHL1TARGETN) +APP2NOSAL = TRUE +APP2RPATH = BRAND +.IF "$(OS)" == "WNT" +APP2ICON = $(SOLARRESDIR)$/icons/ooo3_main_app.ico +APP2LINKRES = $(MISC)$/$(TARGET)2.res +.ENDIF + +SHL1TARGET = unopkgapp +SHL1OBJS = $(SLOFILES) $(SLO)$/lockfile.obj +SHL1STDLIBS = \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(COMPHELPERLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(VCLLIB) \ + $(DEPLOYMENTMISCLIB) +SHL1VERSIONMAP = version.map +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = \ + $(SLO)$/unopkg_app.obj \ + $(SLO)$/unopkg_cmdenv.obj \ + $(SLO)$/unopkg_misc.obj + +OBJFILES = $(OBJ)$/unopkg_main.obj + +.INCLUDE : target.mk + +.IF "$(APP1TARGETN)" != "" # not set during depend=x +$(APP1TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP1TARGETN)"!="" + +$(MISC)$/binso_created.flg: + @@-$(MKDIRHIER) $(BIN)$/so && $(TOUCH) $@ + @@-$(MKDIRHIER) $(MISC)$/so && $(TOUCH) $@ + diff --git a/desktop/source/pkgchk/unopkg/unopkg_app.cxx b/desktop/source/pkgchk/unopkg/unopkg_app.cxx new file mode 100644 index 000000000000..5fc4136a9501 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_app.cxx @@ -0,0 +1,512 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unopkg_app.cxx,v $ + * $Revision: 1.14.58.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove + +#include "dp_misc.h" +#include "unopkg_main.h" +#include "unopkg_shared.h" +#include "dp_identifier.hxx" +#include "sal/main.h" +#include "tools/extendapplicationenvironment.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "osl/thread.h" +#include "osl/process.h" +#include "osl/conditn.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/anytostring.hxx" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/deployment/ui/PackageManagerDialog.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "boost/scoped_array.hpp" +#include "com/sun/star/ui/dialogs/XDialogClosedListener.hpp" +#include "com/sun/star/bridge/XBridgeFactory.hpp" +#include <stdio.h> +#include <vector> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::unopkg; +using ::rtl::OUString; +namespace css = ::com::sun::star; +namespace { + +//------------------------------------------------------------------------------ +const char s_usingText [] = +"\n" +"using: " APP_NAME " add <options> extension-path...\n" +" " APP_NAME " remove <options> extension-identifier...\n" +" " APP_NAME " list <options> extension-identifier...\n" +" " APP_NAME " reinstall <options>\n" +" " APP_NAME " gui\n" +" " APP_NAME " -V\n" +" " APP_NAME " -h\n" +"\n" +"sub-commands:\n" +" add add extension\n" +" remove remove extensions by identifier\n" +" reinstall expert feature: reinstall all deployed extensions\n" +" list list information about deployed extensions\n" +" gui raise Extension Manager Graphical User Interface (GUI)\n" +"\n" +"options:\n" +" -h, --help this help\n" +" -V, --version version information\n" +" -v, --verbose verbose output to stdout\n" +" -f, --force force overwriting existing extensions\n" +" --log-file <file> custom log file; default: <cache-dir>/log.txt\n" +" --shared expert feature: operate on shared installation\n" +" deployment context;\n" +" run only when no concurrent Office\n" +" process(es) are running!\n" +" --deployment-context expert feature: explicit deployment context\n" +" <context>\n" +"\n" +"To learn more about the Extension Manager and extensions, see:\n" +"http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Extensions/Extensions\n\n"; + +//------------------------------------------------------------------------------ +const OptionInfo s_option_infos [] = { + { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false }, + { RTL_CONSTASCII_STRINGPARAM("version"), 'V', false }, + { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false }, + { RTL_CONSTASCII_STRINGPARAM("force"), 'f', false }, + { RTL_CONSTASCII_STRINGPARAM("log-file"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("shared"), '\0', false }, + { RTL_CONSTASCII_STRINGPARAM("deployment-context"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("bundled"), '\0', false}, + + { 0, 0, '\0', false } +}; + +class DialogClosedListenerImpl : + public ::cppu::WeakImplHelper1< ui::dialogs::XDialogClosedListener > +{ + osl::Condition & m_rDialogClosedCondition; + +public: + DialogClosedListenerImpl( osl::Condition & rDialogClosedCondition ) + : m_rDialogClosedCondition( rDialogClosedCondition ) {} + + // XEventListener (base of XDialogClosedListener) + virtual void SAL_CALL disposing( lang::EventObject const & Source ) + throw (RuntimeException); + + // XDialogClosedListener + virtual void SAL_CALL dialogClosed( + ui::dialogs::DialogClosedEvent const & aEvent ) + throw (RuntimeException); +}; + +// XEventListener (base of XDialogClosedListener) +void DialogClosedListenerImpl::disposing( lang::EventObject const & ) + throw (RuntimeException) +{ + // nothing to do +} + +// XDialogClosedListener +void DialogClosedListenerImpl::dialogClosed( + ui::dialogs::DialogClosedEvent const & ) + throw (RuntimeException) +{ + m_rDialogClosedCondition.set(); +} + +// If a package had been installed with a pre OOo 2.2, it could not normally be +// found via its identifier; similarly (and for ease of use), a package +// installed with OOo 2.2 or later could not normally be found via its file +// name. +Reference<deployment::XPackage> findPackage( + Reference<deployment::XPackageManager> const & manager, + Reference<ucb::XCommandEnvironment > const & environment, + OUString const & idOrFileName ) +{ + Sequence< Reference<deployment::XPackage> > ps( + manager->getDeployedPackages( + Reference<task::XAbortChannel>(), environment ) ); + for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) + if ( dp_misc::getIdentifier( ps[i] ) == idOrFileName ) + return ps[i]; + for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) + if ( ps[i]->getName() == idOrFileName ) + return ps[i]; + return Reference<deployment::XPackage>(); +} + +} // anon namespace + + +//workaround for some reason the bridge threads which communicate with the uno.exe +//process are not releases on time +void disposeBridges(Reference<css::uno::XComponentContext> ctx) +{ + if (!ctx.is()) + return; + + Reference<css::bridge::XBridgeFactory> bridgeFac( + ctx->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.bridge.BridgeFactory"), ctx), + UNO_QUERY); + + if (bridgeFac.is()) + { + const Sequence< Reference<css::bridge::XBridge> >seqBridges = bridgeFac->getExistingBridges(); + for (sal_Int32 i = 0; i < seqBridges.getLength(); i++) + { + Reference<css::lang::XComponent> comp(seqBridges[i], UNO_QUERY); + if (comp.is()) + { + try { + comp->dispose(); + } + catch (css::lang::DisposedException& ) + { + } + } + } + } +} + +//############################################################################## +extern "C" int unopkg_main() +{ + tools::extendApplicationEnvironment(); + DisposeGuard disposeGuard; + bool bNoOtherErrorMsg = false; + OUString subCommand; + bool option_shared = false; + bool option_force = false; + bool option_verbose = false; + bool option_bundled = false; + bool subcmd_add = false; + bool subcmd_gui = false; + OUString logFile; + OUString deploymentContext; + OUString cmdArg; + ::std::vector<OUString> cmdPackages; + + OptionInfo const * info_shared = getOptionInfo( + s_option_infos, OUSTR("shared") ); + OptionInfo const * info_force = getOptionInfo( + s_option_infos, OUSTR("force") ); + OptionInfo const * info_verbose = getOptionInfo( + s_option_infos, OUSTR("verbose") ); + OptionInfo const * info_log = getOptionInfo( + s_option_infos, OUSTR("log-file") ); + OptionInfo const * info_context = getOptionInfo( + s_option_infos, OUSTR("deployment-context") ); + OptionInfo const * info_help = getOptionInfo( + s_option_infos, OUSTR("help") ); + OptionInfo const * info_version = getOptionInfo( + s_option_infos, OUSTR("version") ); + OptionInfo const * info_bundled = getOptionInfo( + s_option_infos, OUSTR("bundled") ); + + Reference<XComponentContext> xComponentContext; + Reference<XComponentContext> xLocalComponentContext; + + try { + sal_uInt32 nPos = 0; + sal_uInt32 nCount = osl_getCommandArgCount(); + if (nCount == 0 || isOption( info_help, &nPos )) + { + dp_misc::writeConsole(s_usingText); + return 0; + } + else if (isOption( info_version, &nPos )) { + dp_misc::writeConsole("\n"APP_NAME" Version 3.0\n"); + return 0; + } + //consume all bootstrap variables which may occur before the subcommannd + while(isBootstrapVariable(&nPos)); + + if(nPos >= nCount) + return 0; + //get the sub command + osl_getCommandArg( nPos, &subCommand.pData ); + ++nPos; + subCommand = subCommand.trim(); + subcmd_add = subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("add") ); + subcmd_gui = subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("gui") ); + + // sun-command options and packages: + while (nPos < nCount) + { + if (readArgument( &cmdArg, info_log, &nPos )) { + logFile = makeAbsoluteFileUrl( + cmdArg.trim(), getProcessWorkingDir() ); + } + else if (!readOption( &option_verbose, info_verbose, &nPos ) && + !readOption( &option_shared, info_shared, &nPos ) && + !readOption( &option_force, info_force, &nPos ) && + !readOption( &option_bundled, info_bundled, &nPos ) && + !readArgument( &deploymentContext, info_context, &nPos ) && + !isBootstrapVariable(&nPos)) + { + osl_getCommandArg( nPos, &cmdArg.pData ); + ++nPos; + cmdArg = cmdArg.trim(); + if (cmdArg.getLength() > 0) + { + if (cmdArg[ 0 ] == '-') + { + // is option: + dp_misc::writeConsoleError( + OUSTR("\nERROR: unexpected option ") + + cmdArg + + OUSTR("!\n") + + OUSTR(" Use " APP_NAME " ") + + toString(info_help) + + OUSTR(" to print all options.\n")); + return 1; + } + else + { + // is package: + cmdPackages.push_back( + subcmd_add || subcmd_gui + ? makeAbsoluteFileUrl( + cmdArg, getProcessWorkingDir() ) + : cmdArg ); + } + } + } + } + + //make sure the bundled option was provided together with shared + if (option_bundled && !option_shared) + { + dp_misc::writeConsoleError( + "\nERROR: option --bundled can only be used together with --shared!"); + return 1; + } + + + xComponentContext = getUNO( + disposeGuard, option_verbose, option_shared, subcmd_gui, + xLocalComponentContext ); + + if (deploymentContext.getLength() == 0) { + deploymentContext = option_shared ? OUSTR("shared") : OUSTR("user"); + } + else + { + if (deploymentContext.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("shared") )) { + option_shared = true; + } + else if (option_shared) { + dp_misc::writeConsoleError( + OUSTR("WARNING: explicit context given! ") + + OUSTR("Ignoring option ") + + toString( info_shared ) + + OUSTR("!\n") ); + } + } + + Reference<deployment::XPackageManagerFactory> xPackageManagerFactory( + deployment::thePackageManagerFactory::get( xComponentContext ) ); + Reference<deployment::XPackageManager> xPackageManager( + xPackageManagerFactory->getPackageManager( deploymentContext ) ); + + Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv( + createCmdEnv( xComponentContext, logFile, + option_force, option_verbose, option_bundled) ); + + if (subcmd_add || + subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("remove") )) + { + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + { + OUString const & cmdPackage = cmdPackages[ pos ]; + if (subcmd_add) + { + Reference<deployment::XPackage> xPackage( + xPackageManager->addPackage( + cmdPackage, OUString() /* to be detected */, + Reference<task::XAbortChannel>(), xCmdEnv ) ); + OSL_ASSERT( xPackage.is() ); + } + else + { + try + { + xPackageManager->removePackage( + cmdPackage, cmdPackage, + Reference<task::XAbortChannel>(), xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + Reference<deployment::XPackage> p( + findPackage( + xPackageManager, xCmdEnv, cmdPackage ) ); + //Todo. temporary preventing exception in bundled case. + //In case of a bundled extension, remove would be called as a result of + //uninstalling a rpm. Then we do not want to show an error when the + //extension does not exist, because the package will be uninstalled anyway + //and the error would only confuse people. + if ( !p.is() && !option_bundled) + throw; + else if (p.is()) + xPackageManager->removePackage( + ::dp_misc::getIdentifier(p), p->getName(), + Reference<task::XAbortChannel>(), xCmdEnv ); + } + } + } + } + else if (subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("reinstall") )) + { + xPackageManager->reinstallDeployedPackages( + Reference<task::XAbortChannel>(), xCmdEnv ); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("list") )) + { + Sequence< Reference<deployment::XPackage> > packages; + if (cmdPackages.empty()) + { + packages = xPackageManager->getDeployedPackages( + Reference<task::XAbortChannel>(), xCmdEnv ); + dp_misc::writeConsole( + OUSTR("all deployed ") + deploymentContext + OUSTR(" packages:\n")); + } + else + { + packages.realloc( cmdPackages.size() ); + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + try + { + packages[ pos ] = xPackageManager->getDeployedPackage( + cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + packages[ pos ] = findPackage( + xPackageManager, xCmdEnv, cmdPackages[ pos ] ); + if ( !packages[ pos ].is() ) + throw; + } + } + printf_packages( packages, xCmdEnv ); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("gui") )) + { + Reference<ui::dialogs::XAsynchronousExecutableDialog> xDialog( + deployment::ui::PackageManagerDialog::createAndInstall( + xComponentContext, + cmdPackages.size() > 0 ? cmdPackages[0] : OUString() )); + + osl::Condition dialogEnded; + dialogEnded.reset(); + + Reference< ui::dialogs::XDialogClosedListener > xListener( + new DialogClosedListenerImpl( dialogEnded ) ); + + xDialog->startExecuteModal(xListener); + dialogEnded.wait(); + } + else + { + dp_misc::writeConsoleError( + OUSTR("\nERROR: unknown sub-command ") + + subCommand + + OUSTR("!\n") + + OUSTR(" Use " APP_NAME " ") + + toString(info_help) + + OUSTR(" to print all options.\n")); + return 1; + } + + if (option_verbose) + dp_misc::writeConsole(OUSTR("\n"APP_NAME" done.\n")); + //Force to release all bridges which connect us to the child processes + disposeBridges(xLocalComponentContext); + return 0; + } + catch (ucb::CommandFailedException &e) + { + dp_misc::writeConsoleError(e.Message + OUSTR("\n")); + bNoOtherErrorMsg = true; + } + catch (ucb::CommandAbortedException &) + { + dp_misc::writeConsoleError("\n"APP_NAME" aborted!\n"); + } + catch (deployment::DeploymentException & exc) + { + OUString cause; + if (option_verbose) + { + cause = ::comphelper::anyToString(exc.Cause); + } + else + { + css::uno::Exception e; + if (exc.Cause >>= e) + cause = e.Message; + } + + dp_misc::writeConsoleError( + OUSTR("\nERROR: ") + exc.Message + OUSTR("\n")); + if (cause.getLength()) + dp_misc::writeConsoleError( + OUSTR(" Cause: ") + cause + OUSTR("\n")); + } + catch (LockFileException & e) + { + if (!subcmd_gui) + dp_misc::writeConsoleError(e.Message); + bNoOtherErrorMsg = true; + } + catch (::com::sun::star::uno::Exception & e ) { + Any exc( ::cppu::getCaughtException() ); + + dp_misc::writeConsoleError( + OUSTR("\nERROR: ") + + OUString(option_verbose ? e.Message + OUSTR("\nException details: \n") + + ::comphelper::anyToString(exc) : e.Message) + + OUSTR("\n")); + } + if (!bNoOtherErrorMsg) + dp_misc::writeConsoleError("\n"APP_NAME" failed.\n"); + disposeBridges(xLocalComponentContext); + return 1; +} + + diff --git a/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx new file mode 100644 index 000000000000..ea0659c63874 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx @@ -0,0 +1,445 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unopkg_cmdenv.cxx,v $ + * $Revision: 1.12.8.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 "com/sun/star/deployment/LicenseIndividualAgreementException.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; + bool m_option_bundled; + Reference< XComponentContext > m_xComponentContext; + Reference< XProgressHandler > m_xLogFile; + + void update_( Any const & Status ) throw (RuntimeException); + void printLicense(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, + bool option_bundled); + + // 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, + bool option_bundled) + : m_logLevel(0), + m_option_force_overwrite( option_force_overwrite ), + m_option_verbose( option_verbose ), + m_option_bundled( option_bundled), + 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& sLicense, bool & accept, bool &decline) +{ + ResMgr * pResMgr = DeploymentResMgr::get(); + OUString s1 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_1, *pResMgr)); + 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::LicenseIndividualAgreementException licAgreementExc; + 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 >>= licAgreementExc) + { + String sResMsg( ResId( RID_STR_UNOPKG_NO_SHARED_ALLOWED, *DeploymentResMgr::get() ) ); + sResMsg.SearchAndReplaceAllAscii( "%NAME", licAgreementExc.ExtensionName ); + dp_misc::writeConsole(OUSTR("\n") + sResMsg + OUSTR("\n\n")); + abort = true; + } + else if (request >>= licExc) + { + bLicenseException = true; + printLicense(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::comparePackageVersions(nc_exc.New, nc_exc.Deployed) + == ::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, + bool option_bundled) +{ + return new CommandEnvironmentImpl( + xContext, logFile, option_force_overwrite, option_verbose, option_bundled); +} + +} // unopkg + diff --git a/desktop/source/pkgchk/unopkg/unopkg_main.c b/desktop/source/pkgchk/unopkg/unopkg_main.c new file mode 100644 index 000000000000..5b715f7aeb59 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_main.c @@ -0,0 +1,39 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unopkg_main.c,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sal/config.h" + +#include "sal/main.h" + +#include "unopkg_main.h" + +SAL_IMPLEMENT_MAIN() { + return unopkg_main(); +} diff --git a/desktop/source/pkgchk/unopkg/unopkg_main.h b/desktop/source/pkgchk/unopkg/unopkg_main.h new file mode 100644 index 000000000000..78cb8ac5a3f7 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_main.h @@ -0,0 +1,46 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unopkg_main.h,v $ + * $Revision: 1.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_DESKTOP_SOURCE_PKGCHK_UNOPKG_UNOPKG_MAIN_H +#define INCLUDED_DESKTOP_SOURCE_PKGCHK_UNOPKG_UNOPKG_MAIN_H + +#include "sal/config.h" + +#if defined __cplusplus +extern "C" { +#endif + +int unopkg_main(void); + +#if defined __cplusplus +} +#endif + +#endif diff --git a/desktop/source/pkgchk/unopkg/unopkg_misc.cxx b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx new file mode 100644 index 000000000000..70b469fa58fa --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx @@ -0,0 +1,509 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unopkg_misc.cxx,v $ + * $Revision: 1.15.52.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "deployment.hrc" +#include "unopkg_shared.h" +#include "dp_identifier.hxx" +#include "../../deployment/gui/dp_gui.hrc" +#include "../../app/lockfile.hxx" +#include "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" +#include "rtl/bootstrap.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "osl/process.h" +#include "osl/file.hxx" +#include "osl/thread.hxx" +#include "tools/getprocessworkingdir.hxx" +#include "ucbhelper/contentbroker.hxx" +#include "ucbhelper/configurationkeys.hxx" +#include "unotools/processfactory.hxx" +#include "unotools/configmgr.hxx" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "cppuhelper/bootstrap.hxx" +#include <stdio.h> + +using ::rtl::OUString; +using ::rtl::OString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; + +namespace unopkg { + +bool getLockFilePath(OUString & out); + +::rtl::OUString toString( OptionInfo const * info ) +{ + OSL_ASSERT( info != 0 ); + ::rtl::OUStringBuffer buf; + buf.appendAscii("--"); + buf.appendAscii(info->m_name); + if (info->m_short_option != '\0') + { + buf.appendAscii(" (short -" ); + buf.append(info->m_short_option ); + buf.appendAscii(")"); + } + if (info->m_has_argument) + buf.appendAscii(" <argument>" ); + return buf.makeStringAndClear(); +} + +//============================================================================== +OptionInfo const * getOptionInfo( + OptionInfo const * list, + OUString const & opt, sal_Unicode copt ) +{ + for ( ; list->m_name != 0; ++list ) + { + OptionInfo const & option_info = *list; + if (opt.getLength() > 0) + { + if (opt.equalsAsciiL( + option_info.m_name, option_info.m_name_length ) && + (copt == '\0' || copt == option_info.m_short_option)) + { + return &option_info; + } + } + else + { + OSL_ASSERT( copt != '\0' ); + if (copt == option_info.m_short_option) + { + return &option_info; + } + } + } + OSL_ENSURE( 0, ::rtl::OUStringToOString( + opt, osl_getThreadTextEncoding() ).getStr() ); + return 0; +} + +//============================================================================== +bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + OSL_ASSERT( option_info != 0 ); + if (osl_getCommandArgCount() <= *pIndex) + return false; + + OUString arg; + osl_getCommandArg( *pIndex, &arg.pData ); + sal_Int32 len = arg.getLength(); + + if (len < 2 || arg[ 0 ] != '-') + return false; + + if (len == 2 && arg[ 1 ] == option_info->m_short_option) + { + ++(*pIndex); + dp_misc::TRACE(OUSTR(__FILE__": identified option \'") + + OUSTR("\'") + OUString( option_info->m_short_option ) + OUSTR("\n")); + return true; + } + if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare( + arg.pData->buffer + 2, option_info->m_name ) == 0) + { + ++(*pIndex); + dp_misc::TRACE(OUSTR( __FILE__": identified option \'") + + OUString::createFromAscii(option_info->m_name) + OUSTR("\'\n")); + return true; + } + return false; +} +//============================================================================== + +bool isBootstrapVariable(sal_uInt32 * pIndex) +{ + OSL_ASSERT(osl_getCommandArgCount() >= *pIndex); + + OUString arg; + osl_getCommandArg(*pIndex, &arg.pData); + if (arg.matchAsciiL("-env:", 5)) + { + ++(*pIndex); + return true; + } + return false; +} + +//============================================================================== +bool readArgument( + OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + if (isOption( option_info, pIndex )) + { + if (*pIndex < osl_getCommandArgCount()) + { + OSL_ASSERT( pValue != 0 ); + osl_getCommandArg( *pIndex, &pValue->pData ); + dp_misc::TRACE(OUSTR( __FILE__": argument value: ") + + *pValue + OUSTR("\n")); + ++(*pIndex); + return true; + } + --(*pIndex); + } + return false; +} + +//############################################################################## + +namespace { +struct ExecutableDir : public rtl::StaticWithInit< + const OUString, ExecutableDir> { + const OUString operator () () { + OUString path; + if (osl_getExecutableFile( &path.pData ) != osl_Process_E_None) { + throw RuntimeException( + OUSTR("cannot locate executable directory!"),0 ); + } + return path.copy( 0, path.lastIndexOf( '/' ) ); + } +}; +struct ProcessWorkingDir : public rtl::StaticWithInit< + const OUString, ProcessWorkingDir> { + const OUString operator () () { + OUString workingDir; + tools::getProcessWorkingDir(&workingDir); + return workingDir; + } +}; +} // anon namespace + +//============================================================================== +OUString const & getExecutableDir() +{ + return ExecutableDir::get(); +} + +//============================================================================== +OUString const & getProcessWorkingDir() +{ + return ProcessWorkingDir::get(); +} + +//============================================================================== +OUString makeAbsoluteFileUrl( + OUString const & sys_path, OUString const & base_url, bool throw_exc ) +{ + // system path to file url + OUString file_url; + oslFileError rc = osl_getFileURLFromSystemPath( sys_path.pData, &file_url.pData ); + if ( rc != osl_File_E_None) { + OUString tempPath; + if ( osl_getSystemPathFromFileURL( sys_path.pData, &tempPath.pData) == osl_File_E_None ) + { + file_url = sys_path; + } + else if (throw_exc) + { + throw RuntimeException( + OUSTR("cannot get file url from system path: ") + + sys_path, Reference< XInterface >() ); + } + } + + OUString abs; + if (osl_getAbsoluteFileURL( + base_url.pData, file_url.pData, &abs.pData ) != osl_File_E_None) + { + if (throw_exc) { + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "making absolute file url failed: \"") ); + buf.append( base_url ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\" (base-url) and \"") ); + buf.append( file_url ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" (file-url)!") ); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >() ); + } + return OUString(); + } + return abs[ abs.getLength() -1 ] == '/' + ? abs.copy( 0, abs.getLength() -1 ) : abs; +} + +//############################################################################## + +namespace { + +//------------------------------------------------------------------------------ +inline void printf_space( sal_Int32 space ) +{ + while (space--) + dp_misc::writeConsole(" "); +} + +//------------------------------------------------------------------------------ +void printf_line( + OUString const & name, OUString const & value, sal_Int32 level ) +{ + printf_space( level ); + dp_misc::writeConsole(name + OUSTR(": ") + value + OUSTR("\n")); +} + +//------------------------------------------------------------------------------ +void printf_package( + Reference<deployment::XPackage> const & xPackage, + Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level ) +{ + beans::Optional< OUString > id( + level == 0 + ? beans::Optional< OUString >( + true, dp_misc::getIdentifier( xPackage ) ) + : xPackage->getIdentifier() ); + if (id.IsPresent) + printf_line( OUSTR("Identifier"), id.Value, level ); + OUString version(xPackage->getVersion()); + if (version.getLength() != 0) + printf_line( OUSTR("Version"), version, level + 1 ); + printf_line( OUSTR("URL"), xPackage->getURL(), level + 1 ); + + beans::Optional< beans::Ambiguous<sal_Bool> > option( + xPackage->isRegistered( Reference<task::XAbortChannel>(), xCmdEnv ) ); + OUString value; + if (option.IsPresent) { + beans::Ambiguous<sal_Bool> const & reg = option.Value; + if (reg.IsAmbiguous) + value = OUSTR("unknown"); + else + value = reg.Value ? OUSTR("yes") : OUSTR("no"); + } + else + value = OUSTR("n/a"); + printf_line( OUSTR("is registered"), value, level + 1 ); + + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) { + printf_line( OUSTR("Media-Type"), + xPackageType->getMediaType(), level + 1 ); + } + printf_line( OUSTR("Description"), xPackage->getDescription(), level + 1 ); + if (xPackage->isBundle()) { + Sequence< Reference<deployment::XPackage> > seq( + xPackage->getBundle( Reference<task::XAbortChannel>(), xCmdEnv ) ); + printf_space( level + 1 ); + dp_misc::writeConsole("bundled Packages: {\n"); + printf_packages( seq, xCmdEnv, level + 2 ); + printf_space( level + 1 ); + dp_misc::writeConsole("}\n"); + } +} + +} // anon namespace + +//============================================================================== +void printf_packages( + Sequence< Reference<deployment::XPackage> > const & seq, + Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level ) +{ + sal_Int32 len = seq.getLength(); + Reference< deployment::XPackage > const * p = seq.getConstArray(); + if (len == 0) { + printf_space( level ); + dp_misc::writeConsole("<none>\n"); + } + else { + for ( sal_Int32 pos = 0; pos < len; ++pos ) + printf_package( p[ pos ], xCmdEnv, level ); + } +} + +//############################################################################## + +namespace { + +//------------------------------------------------------------------------------ +Reference<XComponentContext> bootstrapStandAlone( + DisposeGuard & disposeGuard, bool /*verbose */) +{ + Reference<XComponentContext> xContext = + ::cppu::defaultBootstrap_InitialComponentContext(); + + // assure disposing of local component context: + disposeGuard.reset( + Reference<lang::XComponent>( xContext, UNO_QUERY ) ); + + Reference<lang::XMultiServiceFactory> xServiceManager( + xContext->getServiceManager(), UNO_QUERY_THROW ); + // set global process service factory used by unotools config helpers + ::utl::setProcessServiceFactory( xServiceManager ); + + // initialize the ucbhelper ucb, + // because the package implementation uses it + Sequence<Any> ucb_args( 2 ); + ucb_args[ 0 ] <<= OUSTR(UCB_CONFIGURATION_KEY1_LOCAL); + ucb_args[ 1 ] <<= OUSTR(UCB_CONFIGURATION_KEY2_OFFICE); + if (! ::ucbhelper::ContentBroker::initialize( xServiceManager, ucb_args )) + throw RuntimeException( OUSTR("cannot initialize UCB!"), 0 ); + + return xContext; +} + +//------------------------------------------------------------------------------ +Reference<XComponentContext> connectToOffice( + Reference<XComponentContext> const & xLocalComponentContext, + bool verbose ) +{ + Sequence<OUString> args( 3 ); + args[ 0 ] = OUSTR("-nologo"); + args[ 1 ] = OUSTR("-nodefault"); + + OUString pipeId( ::dp_misc::generateRandomPipeId() ); + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("-accept=pipe,name=") ); + buf.append( pipeId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(";urp;") ); + args[ 2 ] = buf.makeStringAndClear(); + OUString appURL( getExecutableDir() + OUSTR("/soffice") ); + + if (verbose) + { + dp_misc::writeConsole( + OUSTR("Raising process: ") + + appURL + + OUSTR("\nArguments: -nologo -nodefault ") + + args[2] + + OUSTR("\n")); + } + + ::dp_misc::raiseProcess( appURL, args ); + + if (verbose) + dp_misc::writeConsole("Ok. Connecting..."); + + OSL_ASSERT( buf.getLength() == 0 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") ); + buf.append( pipeId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + ";urp;StarOffice.ComponentContext") ); + Reference<XComponentContext> xRet( + ::dp_misc::resolveUnoURL( + buf.makeStringAndClear(), xLocalComponentContext ), + UNO_QUERY_THROW ); + if (verbose) + dp_misc::writeConsole("Ok.\n"); + + return xRet; +} + +} // anon namespace + +/** returns the path to the lock file used by unopkg. + @return the path. An empty string signifies an error. +*/ +OUString getLockFilePath() +{ + OUString ret; + OUString sBootstrap(RTL_CONSTASCII_USTRINGPARAM("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}")); + rtl::Bootstrap::expandMacros(sBootstrap); + OUString sAbs; + if (::osl::File::E_None == ::osl::File::getAbsoluteFileURL( + sBootstrap, OUSTR(".lock"), sAbs)) + { + if (::osl::File::E_None == + ::osl::File::getSystemPathFromFileURL(sAbs, sBootstrap)) + { + ret = sBootstrap; + } + } + + return ret; +} +//============================================================================== +Reference<XComponentContext> getUNO( + DisposeGuard & disposeGuard, bool verbose, bool shared, bool bGui, + Reference<XComponentContext> & out_localContext) +{ + // do not create any user data (for the root user) in --shared mode: + if (shared) { + rtl::Bootstrap::set( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CFG_CacheUrl")), + rtl::OUString()); + } + + // hold lock during process runtime: + static ::desktop::Lockfile s_lockfile( false /* no IPC server */ ); + Reference<XComponentContext> xComponentContext( + bootstrapStandAlone( disposeGuard, verbose ) ); + out_localContext = xComponentContext; + if (::dp_misc::office_is_running()) { + xComponentContext.set( + connectToOffice( xComponentContext, verbose ) ); + } + else + { + if (! s_lockfile.check( 0 )) + { + String sMsg(ResId(RID_STR_CONCURRENTINSTANCE, *DeploymentResMgr::get())); + //Create this string before we call DeInitVCL, because this will kill + //the ResMgr + String sError(ResId(RID_STR_UNOPKG_ERROR, *DeploymentResMgr::get())); + + sMsg = sMsg + OUSTR("\n") + getLockFilePath(); + + if (bGui) + { + //We show a message box or print to the console that there + //is another instance already running + if ( ! InitVCL( Reference<lang::XMultiServiceFactory>( + xComponentContext->getServiceManager(), + UNO_QUERY_THROW ) )) + throw RuntimeException( OUSTR("Cannot initialize VCL!"), + NULL ); + { + WarningBox warn(NULL, WB_OK | WB_DEF_OK, sMsg); + warn.SetText(::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME).get<OUString>()); + warn.SetIcon(0); + warn.Execute(); + } + DeInitVCL(); + } + + throw LockFileException( + OUSTR("\n") + sError + sMsg + OUSTR("\n")); + } + } + + return xComponentContext; +} + +} + diff --git a/desktop/source/pkgchk/unopkg/unopkg_shared.h b/desktop/source/pkgchk/unopkg/unopkg_shared.h new file mode 100644 index 000000000000..18314811f63f --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_shared.h @@ -0,0 +1,186 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unopkg_shared.h,v $ + * $Revision: 1.9.8.3 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "dp_misc.h" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "tools/resmgr.hxx" +#include "rtl/ustring.hxx" +#include "unotools/configmgr.hxx" + + +#define APP_NAME "unopkg" + +namespace css = ::com::sun::star; + +namespace unopkg { + + inline ::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang ) + { + ::com::sun::star::lang::Locale locale; + sal_Int32 nIndex = 0; + locale.Language = slang.getToken( 0, '-', nIndex ); + locale.Country = slang.getToken( 0, '-', nIndex ); + locale.Variant = slang.getToken( 0, '-', nIndex ); + return locale; + } + + + struct OfficeLocale : + public rtl::StaticWithInit<const css::lang::Locale, OfficeLocale> { + const css::lang::Locale operator () () { + ::rtl::OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw css::uno::RuntimeException( OUSTR("Cannot determine language!"), 0 ); + if (slang.getLength() == 0) + slang = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US")); + return toLocale(slang); + } +}; + +struct DeploymentResMgr : public rtl::StaticWithInit< ResMgr *, DeploymentResMgr > +{ + ResMgr * operator () () { + return ResMgr::CreateResMgr( "deployment", OfficeLocale::get()); + } +}; + +struct OptionInfo +{ + char const * m_name; + sal_uInt32 m_name_length; + sal_Unicode m_short_option; + bool m_has_argument; +}; + +struct LockFileException : public css::uno::Exception +{ + LockFileException(::rtl::OUString const & sMessage) : + css::uno::Exception(sMessage, css::uno::Reference< css::uno::XInterface > ()) {} +}; + +//============================================================================== +::rtl::OUString toString( OptionInfo const * info ); + +//============================================================================== +OptionInfo const * getOptionInfo( + OptionInfo const * list, + ::rtl::OUString const & opt, sal_Unicode copt = '\0' ); + +//============================================================================== +bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex ); + +//============================================================================== +bool readArgument( + ::rtl::OUString * pValue, OptionInfo const * option_info, + sal_uInt32 * pIndex ); + +//============================================================================== +inline bool readOption( + bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + if (isOption( option_info, pIndex )) { + OSL_ASSERT( flag != 0 ); + *flag = true; + return true; + } + return false; +} +//============================================================================== + +/** checks if an argument is a bootstrap variable. These start with -env:. For example + -env:UNO_JAVA_JFW_USER_DATA=file:///d:/user +*/ +bool isBootstrapVariable(sal_uInt32 * pIndex); +//============================================================================== +::rtl::OUString const & getExecutableDir(); + +//============================================================================== +::rtl::OUString const & getProcessWorkingDir(); + +//============================================================================== +::rtl::OUString makeAbsoluteFileUrl( + ::rtl::OUString const & sys_path, ::rtl::OUString const & base_url, + bool throw_exc = true ); + +//############################################################################## + +//============================================================================== +class DisposeGuard +{ + css::uno::Reference<css::lang::XComponent> m_xComp; + +public: + inline DisposeGuard() {} + inline DisposeGuard( + css::uno::Reference<css::lang::XComponent> const & xComp ) + : m_xComp( xComp ) {} + + inline ~DisposeGuard() + { + if (m_xComp.is()) + m_xComp->dispose(); + } + + inline void reset( + css::uno::Reference<css::lang::XComponent> const & xComp ) + { + m_xComp = xComp; + } +}; + +//============================================================================== +css::uno::Reference<css::ucb::XCommandEnvironment> createCmdEnv( + css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & logFile, + bool option_force_overwrite, + bool option_verbose, + bool option_bundled); + +//============================================================================== +void printf_packages( + css::uno::Sequence< + css::uno::Reference<css::deployment::XPackage> > const & seq, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + sal_Int32 level = 0 ); + +//############################################################################## + +//============================================================================== +css::uno::Reference<css::uno::XComponentContext> getUNO( + DisposeGuard & disposeGuard, bool verbose, bool shared, bool bGui, + css::uno::Reference<css::uno::XComponentContext> & out_LocalComponentContext); + +} + diff --git a/desktop/source/pkgchk/unopkg/version.map b/desktop/source/pkgchk/unopkg/version.map new file mode 100644 index 000000000000..b770ff129565 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/version.map @@ -0,0 +1,38 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: version.map,v $ +# +# $Revision: 1.3 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +unopkg.3 { + global: + unopkg_main; + + local: + *; +}; |